From 9d96c169227ecc60fddf8497e740f7a38a05f361 Mon Sep 17 00:00:00 2001 From: martin Date: Fri, 31 Aug 2018 17:35:51 +0000 Subject: [PATCH] Pull up following revision(s) (requested by riastradh in ticket #996): sys/external/bsd/drm2/dist/drm/nouveau/nouveau_nv84_fence.c: revision 1.3 sys/external/bsd/drm2/dist/drm/nouveau/nouveau_fence.h: revision 1.3 sys/external/bsd/drm2/dist/drm/nouveau/nouveau_fence.h: revision 1.4 sys/external/bsd/drm2/dist/drm/nouveau/nouveau_fence.h: revision 1.5 sys/external/bsd/drm2/dist/drm/nouveau/nouveau_fence.c: revision 1.5 sys/external/bsd/drm2/dist/drm/nouveau/nouveau_fence.c: revision 1.6 sys/external/bsd/drm2/dist/drm/nouveau/nouveau_fence.c: revision 1.7 sys/external/bsd/drm2/dist/drm/nouveau/nouveau_fence.c: revision 1.8 sys/external/bsd/drm2/dist/drm/nouveau/nouveau_fence.c: revision 1.9 Rewrite nouveau_fence in an attempt to make it make sense. PR kern/53441 XXX pullup-7 XXX pullup-8 Fences may last longer than their channels. - Use a reference count on the nouveau_fence_chan object. - Acquire it with kpreemption disabled. - Use xcall to wait for kpreempt-disabled sections to complete. PR kern/53441 XXX pullup-7 XXX pullup-8 Defer nouveau_fence_unref until spin unlock. - kfree while holding a spin lock is not a good idea. - Make sure we GC every time we might signal fences. PR kern/53441 XXX pullup-7 XXX pullup-8 Attempt to make sense of return values of nouveau_fence_wait. PR kern/53441 XXX pullup-7 XXX pullup-8 Fix edge case of reference counting, oops. PR kern/53441 XXX pullup-7 XXX pullup-8 --- .../bsd/drm2/dist/drm/nouveau/nouveau_fence.c | 488 ++++++++++++++---- .../bsd/drm2/dist/drm/nouveau/nouveau_fence.h | 20 +- .../dist/drm/nouveau/nouveau_nv84_fence.c | 15 +- 3 files changed, 390 insertions(+), 133 deletions(-) diff --git a/sys/external/bsd/drm2/dist/drm/nouveau/nouveau_fence.c b/sys/external/bsd/drm2/dist/drm/nouveau/nouveau_fence.c index 2a83285e07da..8bc6f1687446 100644 --- a/sys/external/bsd/drm2/dist/drm/nouveau/nouveau_fence.c +++ b/sys/external/bsd/drm2/dist/drm/nouveau/nouveau_fence.c @@ -1,4 +1,4 @@ -/* $NetBSD: nouveau_fence.c,v 1.4 2016/04/13 07:57:15 riastradh Exp $ */ +/* $NetBSD: nouveau_fence.c,v 1.4.10.1 2018/08/31 17:35:51 martin Exp $ */ /* * Copyright (C) 2007 Ben Skeggs. @@ -27,7 +27,10 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: nouveau_fence.c,v 1.4 2016/04/13 07:57:15 riastradh Exp $"); +__KERNEL_RCSID(0, "$NetBSD: nouveau_fence.c,v 1.4.10.1 2018/08/31 17:35:51 martin Exp $"); + +#include +#include #include @@ -41,6 +44,12 @@ __KERNEL_RCSID(0, "$NetBSD: nouveau_fence.c,v 1.4 2016/04/13 07:57:15 riastradh #include +/* + * struct fence_work + * + * State for a work action scheduled when a fence is completed. + * Will call func(data) at some point after that happens. + */ struct fence_work { struct work_struct base; struct list_head head; @@ -48,101 +57,291 @@ struct fence_work { void *data; }; +/* + * nouveau_fence_channel_acquire(fence) + * + * Try to return the channel associated with fence. + */ +static struct nouveau_channel * +nouveau_fence_channel_acquire(struct nouveau_fence *fence) +{ + struct nouveau_channel *chan; + struct nouveau_fence_chan *fctx; + + /* + * Block cross-calls while we examine fence. If we observe + * that fence->done is false, then the channel cannot be + * destroyed even by another CPU until after kpreempt_enable. + */ + kpreempt_disable(); + if (fence->done) { + chan = NULL; + } else { + chan = fence->channel; + fctx = chan->fence; + atomic_inc_uint(&fctx->refcnt); + } + kpreempt_enable(); + + return chan; +} + +/* + * nouveau_fence_gc_grab(fctx, list) + * + * Move all of channel's done fences to list. + * + * Caller must hold channel's fence lock. + */ +static void +nouveau_fence_gc_grab(struct nouveau_fence_chan *fctx, struct list_head *list) +{ + struct list_head *node, *next; + + BUG_ON(!spin_is_locked(&fctx->lock)); + + list_for_each_safe(node, next, &fctx->done) { + list_move_tail(node, list); + } +} + +/* + * nouveau_fence_gc_free(list) + * + * Unreference all of the fences in the list. + * + * Caller MUST NOT hold the fences' channel's fence lock. + */ +static void +nouveau_fence_gc_free(struct list_head *list) +{ + struct nouveau_fence *fence, *next; + + list_for_each_entry_safe(fence, next, list, head) { + list_del(&fence->head); + nouveau_fence_unref(&fence); + } +} + +/* + * nouveau_fence_channel_release(channel) + * + * Release the channel acquired with nouveau_fence_channel_acquire. + */ +static void +nouveau_fence_channel_release(struct nouveau_channel *chan) +{ + struct nouveau_fence_chan *fctx = chan->fence; + unsigned old, new; + + do { + old = fctx->refcnt; + if (old == 1) { + spin_lock(&fctx->lock); + if (atomic_dec_uint_nv(&fctx->refcnt) == 0) + DRM_SPIN_WAKEUP_ALL(&fctx->waitqueue, + &fctx->lock); + spin_unlock(&fctx->lock); + return; + } + new = old - 1; + } while (atomic_cas_uint(&fctx->refcnt, old, new) != old); +} + +/* + * nouveau_fence_signal(fence) + * + * Schedule all the work for fence's completion, mark it done, and + * move it from the pending list to the done list. + * + * Caller must hold fence's channel's fence lock. + */ static void nouveau_fence_signal(struct nouveau_fence *fence) { + struct nouveau_channel *chan __diagused = fence->channel; + struct nouveau_fence_chan *fctx __diagused = chan->fence; struct fence_work *work, *temp; + BUG_ON(!spin_is_locked(&fctx->lock)); + BUG_ON(fence->done); + + /* Schedule all the work for this fence. */ list_for_each_entry_safe(work, temp, &fence->work, head) { schedule_work(&work->base); list_del(&work->head); } - fence->channel = NULL; - list_del(&fence->head); + /* Note that the fence is done. */ + fence->done = true; + + /* Move it from the pending list to the done list. */ + list_move_tail(&fence->head, &fctx->done); } +static void +nouveau_fence_context_del_xc(void *a, void *b) +{ +} + +/* + * nouveau_fence_context_del(fctx) + * + * Artificially complete all fences in fctx, wait for their work + * to drain, and destroy the memory associated with fctx. + */ void nouveau_fence_context_del(struct nouveau_fence_chan *fctx) { struct nouveau_fence *fence, *fnext; + struct list_head done_list; + int ret __diagused; + + INIT_LIST_HEAD(&done_list); + + /* Signal all the fences in fctx. */ spin_lock(&fctx->lock); list_for_each_entry_safe(fence, fnext, &fctx->pending, head) { nouveau_fence_signal(fence); } + nouveau_fence_gc_grab(fctx, &done_list); spin_unlock(&fctx->lock); + + /* Release any fences that we signalled. */ + nouveau_fence_gc_free(&done_list); + + /* Wait for the workqueue to drain. */ + flush_scheduled_work(); + + /* Wait for nouveau_fence_channel_acquire to complete on all CPUs. */ + xc_wait(xc_broadcast(0, nouveau_fence_context_del_xc, NULL, NULL)); + + /* Release our reference and wait for any others to drain. */ + spin_lock(&fctx->lock); + KASSERT(fctx->refcnt > 0); + atomic_dec_uint(&fctx->refcnt); + DRM_SPIN_WAIT_NOINTR_UNTIL(ret, &fctx->waitqueue, &fctx->lock, + fctx->refcnt == 0); + BUG_ON(ret); + spin_unlock(&fctx->lock); + + /* Make sure there are no more fences on the list. */ + BUG_ON(!list_empty(&fctx->done)); + BUG_ON(!list_empty(&fctx->flip)); + BUG_ON(!list_empty(&fctx->pending)); + + /* Destroy the fence context. */ + DRM_DESTROY_WAITQUEUE(&fctx->waitqueue); spin_lock_destroy(&fctx->lock); } +/* + * nouveau_fence_context_new(fctx) + * + * Initialize the state fctx for all fences on a channel. + */ void nouveau_fence_context_new(struct nouveau_fence_chan *fctx) { + INIT_LIST_HEAD(&fctx->flip); INIT_LIST_HEAD(&fctx->pending); + INIT_LIST_HEAD(&fctx->done); spin_lock_init(&fctx->lock); + DRM_INIT_WAITQUEUE(&fctx->waitqueue, "nvfnchan"); + fctx->refcnt = 1; } +/* + * nouveau_fence_work_handler(kwork) + * + * Work handler for nouveau_fence_work. + */ static void nouveau_fence_work_handler(struct work_struct *kwork) { struct fence_work *work = container_of(kwork, typeof(*work), base); + work->func(work->data); kfree(work); } +/* + * nouveau_fence_work(fence, func, data) + * + * Arrange to call func(data) after fence is completed. If fence + * is already completed, call it immediately. If memory is + * scarce, synchronously wait for the fence and call it. + */ void nouveau_fence_work(struct nouveau_fence *fence, void (*func)(void *), void *data) { - struct nouveau_channel *chan = fence->channel; + struct nouveau_channel *chan; struct nouveau_fence_chan *fctx; struct fence_work *work = NULL; - if (nouveau_fence_done(fence)) { - func(data); - return; - } - + if ((chan = nouveau_fence_channel_acquire(fence)) == NULL) + goto now0; fctx = chan->fence; + work = kmalloc(sizeof(*work), GFP_KERNEL); - if (!work) { + if (work == NULL) { WARN_ON(nouveau_fence_wait(fence, false, false)); - func(data); - return; + goto now1; } spin_lock(&fctx->lock); - if (!fence->channel) { + if (fence->done) { spin_unlock(&fctx->lock); - kfree(work); - func(data); - return; + goto now2; } - INIT_WORK(&work->base, nouveau_fence_work_handler); work->func = func; work->data = data; list_add(&work->head, &fence->work); + if (atomic_dec_uint_nv(&fctx->refcnt) == 0) + DRM_SPIN_WAKEUP_ALL(&fctx->waitqueue, &fctx->lock); spin_unlock(&fctx->lock); + return; + +now2: kfree(work); +now1: nouveau_fence_channel_release(chan); +now0: func(data); } +/* + * nouveau_fence_update(chan) + * + * Test all fences on chan for completion. For any that are + * completed, mark them as such and schedule work for them. + * + * Caller must hold chan's fence lock. + */ static void nouveau_fence_update(struct nouveau_channel *chan) { struct nouveau_fence_chan *fctx = chan->fence; struct nouveau_fence *fence, *fnext; - spin_lock(&fctx->lock); + BUG_ON(!spin_is_locked(&fctx->lock)); list_for_each_entry_safe(fence, fnext, &fctx->pending, head) { if (fctx->read(chan) < fence->sequence) break; - nouveau_fence_signal(fence); - nouveau_fence_unref(&fence); } - spin_unlock(&fctx->lock); + BUG_ON(!spin_is_locked(&fctx->lock)); } +/* + * nouveau_fence_emit(fence, chan) + * + * - Initialize fence. + * - Set its timeout to 15 sec from now. + * - Assign it the next sequence number on channel. + * - Submit it to the device with the device-specific emit routine. + * - If that succeeds, add it to the list of pending fences on chan. + */ int nouveau_fence_emit(struct nouveau_fence *fence, struct nouveau_channel *chan) { @@ -151,7 +350,9 @@ nouveau_fence_emit(struct nouveau_fence *fence, struct nouveau_channel *chan) fence->channel = chan; fence->timeout = jiffies + (15 * HZ); + spin_lock(&fctx->lock); fence->sequence = ++fctx->sequence; + spin_unlock(&fctx->lock); ret = fctx->emit(fence); if (!ret) { @@ -164,129 +365,197 @@ nouveau_fence_emit(struct nouveau_fence *fence, struct nouveau_channel *chan) return ret; } +/* + * nouveau_fence_done_locked(fence, chan) + * + * Test whether fence, which must be on chan, is done. If it is + * not marked as done, poll all fences on chan first. + * + * Caller must hold chan's fence lock. + */ +static bool +nouveau_fence_done_locked(struct nouveau_fence *fence, + struct nouveau_channel *chan) +{ + struct nouveau_fence_chan *fctx __diagused = chan->fence; + + BUG_ON(!spin_is_locked(&fctx->lock)); + BUG_ON(fence->channel != chan); + + /* If it's not done, poll it for changes. */ + if (!fence->done) + nouveau_fence_update(chan); + + /* Check, possibly again, whether it is done now. */ + return fence->done; +} + +/* + * nouveau_fence_done(fence) + * + * Test whether fence is done. If it is not marked as done, poll + * all fences on its channel first. Caller MUST NOT hold the + * fence lock. + */ bool nouveau_fence_done(struct nouveau_fence *fence) { - if (fence->channel) - nouveau_fence_update(fence->channel); - return !fence->channel; + struct nouveau_channel *chan; + struct nouveau_fence_chan *fctx; + struct list_head done_list; + bool done; + + if ((chan = nouveau_fence_channel_acquire(fence)) == NULL) + return true; + + INIT_LIST_HEAD(&done_list); + + fctx = chan->fence; + spin_lock(&fctx->lock); + done = nouveau_fence_done_locked(fence, chan); + nouveau_fence_gc_grab(fctx, &done_list); + spin_unlock(&fctx->lock); + + nouveau_fence_channel_release(chan); + + nouveau_fence_gc_free(&done_list); + + return done; } +/* + * nouveau_fence_wait_uevent_handler(data, index) + * + * Nouveau uevent handler for fence completion. data is a + * nouveau_fence_chan pointer. Simply wake up all threads waiting + * for completion of any fences on the channel. Does not mark + * fences as completed -- threads must poll fences for completion. + */ static int nouveau_fence_wait_uevent_handler(void *data, int index) { - struct nouveau_fence_priv *priv = data; -#ifdef __NetBSD__ - spin_lock(&priv->waitlock); - /* XXX Set a flag... */ - DRM_SPIN_WAKEUP_ALL(&priv->waitqueue, &priv->waitlock); - spin_unlock(&priv->waitlock); -#else - wake_up_all(&priv->waiting); -#endif + struct nouveau_fence_chan *fctx = data; + + spin_lock(&fctx->lock); + DRM_SPIN_WAKEUP_ALL(&fctx->waitqueue, &fctx->lock); + spin_unlock(&fctx->lock); + return NVKM_EVENT_KEEP; } +/* + * nouveau_fence_wait_uevent(fence, chan, intr) + * + * Wait using a nouveau event for completion of fence on chan. + * Wait interruptibly iff intr is true. + * + * Return 0 if fence was signalled, negative error code on + * timeout (-EBUSY) or interrupt (-ERESTARTSYS) or other error. + */ static int -nouveau_fence_wait_uevent(struct nouveau_fence *fence, bool intr) - +nouveau_fence_wait_uevent(struct nouveau_fence *fence, + struct nouveau_channel *chan, bool intr) { - struct nouveau_channel *chan = fence->channel; struct nouveau_fifo *pfifo = nouveau_fifo(chan->drm->device); - struct nouveau_fence_priv *priv = chan->drm->fence; + struct nouveau_fence_chan *fctx = chan->fence; struct nouveau_eventh *handler; + struct list_head done_list; int ret = 0; + BUG_ON(fence->channel != chan); + ret = nouveau_event_new(pfifo->uevent, 0, nouveau_fence_wait_uevent_handler, - priv, &handler); + fctx, &handler); if (ret) return ret; nouveau_event_get(handler); + INIT_LIST_HEAD(&done_list); + if (fence->timeout) { unsigned long timeout = fence->timeout - jiffies; if (time_before(jiffies, fence->timeout)) { -#ifdef __NetBSD__ - spin_lock(&priv->waitlock); + spin_lock(&fctx->lock); if (intr) { DRM_SPIN_TIMED_WAIT_UNTIL(ret, - &priv->waitqueue, &priv->waitlock, + &fctx->waitqueue, &fctx->lock, timeout, - nouveau_fence_done(fence)); + nouveau_fence_done_locked(fence, chan)); } else { DRM_SPIN_TIMED_WAIT_NOINTR_UNTIL(ret, - &priv->waitqueue, &priv->waitlock, + &fctx->waitqueue, &fctx->lock, timeout, - nouveau_fence_done(fence)); + nouveau_fence_done_locked(fence, chan)); } - spin_unlock(&priv->waitlock); -#else - if (intr) { - ret = wait_event_interruptible_timeout( - priv->waiting, - nouveau_fence_done(fence), - timeout); - } else { - ret = wait_event_timeout(priv->waiting, - nouveau_fence_done(fence), - timeout); - } -#endif - } - - if (ret >= 0) { - fence->timeout = jiffies + ret; - if (time_after_eq(jiffies, fence->timeout)) + nouveau_fence_gc_grab(fctx, &done_list); + spin_unlock(&fctx->lock); + if (ret < 0) { + /* error */ + } else if (ret == 0) { + /* timeout */ ret = -EBUSY; + } else { + /* success */ + ret = 0; + } + } else { + /* timeout */ + ret = -EBUSY; } } else { -#ifdef __NetBSD__ - spin_lock(&priv->waitlock); + spin_lock(&fctx->lock); if (intr) { - DRM_SPIN_WAIT_UNTIL(ret, &priv->waitqueue, - &priv->waitlock, - nouveau_fence_done(fence)); + DRM_SPIN_WAIT_UNTIL(ret, &fctx->waitqueue, + &fctx->lock, + nouveau_fence_done_locked(fence, chan)); } else { - DRM_SPIN_WAIT_NOINTR_UNTIL(ret, &priv->waitqueue, - &priv->waitlock, - nouveau_fence_done(fence)); + DRM_SPIN_WAIT_NOINTR_UNTIL(ret, &fctx->waitqueue, + &fctx->lock, + nouveau_fence_done_locked(fence, chan)); } - spin_unlock(&priv->waitlock); -#else - if (intr) { - ret = wait_event_interruptible(priv->waiting, - nouveau_fence_done(fence)); - } else { - wait_event(priv->waiting, nouveau_fence_done(fence)); - } -#endif + nouveau_fence_gc_grab(fctx, &done_list); + spin_unlock(&fctx->lock); } nouveau_event_ref(NULL, &handler); + + nouveau_fence_gc_free(&done_list); + if (unlikely(ret < 0)) return ret; return 0; } +/* + * nouveau_fence_wait(fence, lazy, intr) + * + * Wait for fence to complete. Wait interruptibly iff intr is + * true. If lazy is true, may sleep, either for a single tick or + * for an interrupt; otherwise will busy-wait. + * + * Return 0 if fence was signalled, negative error code on + * timeout (-EBUSY) or interrupt (-ERESTARTSYS) or other error. + */ int nouveau_fence_wait(struct nouveau_fence *fence, bool lazy, bool intr) { - struct nouveau_channel *chan = fence->channel; - struct nouveau_fence_priv *priv = chan ? chan->drm->fence : NULL; -#ifndef __NetBSD__ - unsigned long sleep_time = NSEC_PER_MSEC / 1000; - ktime_t t; -#endif + struct nouveau_channel *chan; + struct nouveau_fence_priv *priv; + unsigned long delay_usec = 1; int ret = 0; + if ((chan = nouveau_fence_channel_acquire(fence)) == NULL) + goto out0; + + priv = chan->drm->fence; while (priv && priv->uevent && lazy && !nouveau_fence_done(fence)) { - ret = nouveau_fence_wait_uevent(fence, intr); + ret = nouveau_fence_wait_uevent(fence, chan, intr); if (ret < 0) - return ret; + goto out1; } while (!nouveau_fence_done(fence)) { @@ -295,33 +564,19 @@ nouveau_fence_wait(struct nouveau_fence *fence, bool lazy, bool intr) break; } -#ifdef __NetBSD__ - if (lazy) - kpause("nvfencep", intr, 1, NULL); - else - DELAY(1); -#else - __set_current_state(intr ? TASK_INTERRUPTIBLE : - TASK_UNINTERRUPTIBLE); - if (lazy) { - t = ktime_set(0, sleep_time); - schedule_hrtimeout(&t, HRTIMER_MODE_REL); - sleep_time *= 2; - if (sleep_time > NSEC_PER_MSEC) - sleep_time = NSEC_PER_MSEC; + if (lazy && delay_usec >= 1000*hztoms(1)) { + /* XXX errno NetBSD->Linux */ + ret = -kpause("nvfencew", intr, 1, NULL); + if (ret != -EWOULDBLOCK) + break; + } else { + DELAY(delay_usec); + delay_usec *= 2; } - - if (intr && signal_pending(current)) { - ret = -ERESTARTSYS; - break; - } -#endif } -#ifndef __NetBSD__ - __set_current_state(TASK_RUNNING); -#endif - return ret; +out1: nouveau_fence_channel_release(chan); +out0: return ret; } int @@ -331,13 +586,14 @@ nouveau_fence_sync(struct nouveau_fence *fence, struct nouveau_channel *chan) struct nouveau_channel *prev; int ret = 0; - prev = fence ? fence->channel : NULL; - if (prev) { + if (fence != NULL && + (prev = nouveau_fence_channel_acquire(fence)) != NULL) { if (unlikely(prev != chan && !nouveau_fence_done(fence))) { ret = fctx->sync(fence, prev, chan); if (unlikely(ret)) ret = nouveau_fence_wait(fence, true, false); } + nouveau_fence_channel_release(prev); } return ret; @@ -347,12 +603,14 @@ static void nouveau_fence_del(struct kref *kref) { struct nouveau_fence *fence = container_of(kref, typeof(*fence), kref); + kfree(fence); } void nouveau_fence_unref(struct nouveau_fence **pfence) { + if (*pfence) kref_put(&(*pfence)->kref, nouveau_fence_del); *pfence = NULL; @@ -361,6 +619,7 @@ nouveau_fence_unref(struct nouveau_fence **pfence) struct nouveau_fence * nouveau_fence_ref(struct nouveau_fence *fence) { + if (fence) kref_get(&fence->kref); return fence; @@ -382,6 +641,7 @@ nouveau_fence_new(struct nouveau_channel *chan, bool sysmem, INIT_LIST_HEAD(&fence->work); fence->sysmem = sysmem; + fence->done = false; kref_init(&fence->kref); ret = nouveau_fence_emit(fence, chan); diff --git a/sys/external/bsd/drm2/dist/drm/nouveau/nouveau_fence.h b/sys/external/bsd/drm2/dist/drm/nouveau/nouveau_fence.h index f6f12ba1f38f..a0c32455bd55 100644 --- a/sys/external/bsd/drm2/dist/drm/nouveau/nouveau_fence.h +++ b/sys/external/bsd/drm2/dist/drm/nouveau/nouveau_fence.h @@ -9,6 +9,7 @@ struct nouveau_fence { struct kref kref; bool sysmem; + bool done; struct nouveau_channel *channel; unsigned long timeout; @@ -27,9 +28,15 @@ void nouveau_fence_work(struct nouveau_fence *, void (*)(void *), void *); int nouveau_fence_wait(struct nouveau_fence *, bool lazy, bool intr); int nouveau_fence_sync(struct nouveau_fence *, struct nouveau_channel *); +/* + * struct nouveau_fence_chan: + * + * State common to all fences in a single nouveau_channel. + */ struct nouveau_fence_chan { struct list_head pending; struct list_head flip; + struct list_head done; int (*emit)(struct nouveau_fence *); int (*sync)(struct nouveau_fence *, struct nouveau_channel *, @@ -39,9 +46,16 @@ struct nouveau_fence_chan { int (*sync32)(struct nouveau_channel *, u64, u32); spinlock_t lock; + drm_waitqueue_t waitqueue; + volatile unsigned refcnt; u32 sequence; }; +/* + * struct nouveau_fence_priv: + * + * Device-specific operations on fences. + */ struct nouveau_fence_priv { void (*dtor)(struct nouveau_drm *); bool (*suspend)(struct nouveau_drm *); @@ -49,12 +63,6 @@ struct nouveau_fence_priv { int (*context_new)(struct nouveau_channel *); void (*context_del)(struct nouveau_channel *); -#ifdef __NetBSD__ - spinlock_t waitlock; - drm_waitqueue_t waitqueue; -#else - wait_queue_head_t waiting; -#endif bool uevent; }; diff --git a/sys/external/bsd/drm2/dist/drm/nouveau/nouveau_nv84_fence.c b/sys/external/bsd/drm2/dist/drm/nouveau/nouveau_nv84_fence.c index 0bf784f0f11b..fcaaec5e94cc 100644 --- a/sys/external/bsd/drm2/dist/drm/nouveau/nouveau_nv84_fence.c +++ b/sys/external/bsd/drm2/dist/drm/nouveau/nouveau_nv84_fence.c @@ -1,4 +1,4 @@ -/* $NetBSD: nouveau_nv84_fence.c,v 1.2 2015/02/25 14:57:04 riastradh Exp $ */ +/* $NetBSD: nouveau_nv84_fence.c,v 1.2.10.1 2018/08/31 17:35:51 martin Exp $ */ /* * Copyright 2012 Red Hat Inc. @@ -25,7 +25,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: nouveau_nv84_fence.c,v 1.2 2015/02/25 14:57:04 riastradh Exp $"); +__KERNEL_RCSID(0, "$NetBSD: nouveau_nv84_fence.c,v 1.2.10.1 2018/08/31 17:35:51 martin Exp $"); #include #include @@ -216,11 +216,6 @@ nv84_fence_destroy(struct nouveau_drm *drm) { struct nv84_fence_priv *priv = drm->fence; -#ifdef __NetBSD__ - spin_lock_destroy(&priv->base.waitlock); - DRM_DESTROY_WAITQUEUE(&priv->base.waitqueue); -#endif - nouveau_bo_unmap(priv->bo_gart); if (priv->bo_gart) nouveau_bo_unpin(priv->bo_gart); @@ -250,12 +245,6 @@ nv84_fence_create(struct nouveau_drm *drm) priv->base.context_new = nv84_fence_context_new; priv->base.context_del = nv84_fence_context_del; -#ifdef __NetBSD__ - spin_lock_init(&priv->base.waitlock); - DRM_INIT_WAITQUEUE(&priv->base.waitqueue, "nvfenceq"); -#else - init_waitqueue_head(&priv->base.waiting); -#endif priv->base.uevent = true; ret = nouveau_bo_new(drm->dev, 16 * (pfifo->max + 1), 0,