Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/nouveau/fence/nv84-: put processes to sleep while waiting on fences

Signed-off-by: Ben Skeggs <bskeggs@redhat.com>

+92 -5
+1 -1
drivers/gpu/drm/nouveau/nouveau_dma.h
··· 191 191 #define NV84_SUBCHAN_SEMAPHORE_TRIGGER_WRITE_LONG 0x00000002 192 192 #define NV84_SUBCHAN_SEMAPHORE_TRIGGER_ACQUIRE_GEQUAL 0x00000004 193 193 #define NVC0_SUBCHAN_SEMAPHORE_TRIGGER_YIELD 0x00001000 194 - #define NV84_SUBCHAN_NOTIFY_INTR 0x00000020 194 + #define NV84_SUBCHAN_UEVENT 0x00000020 195 195 #define NV84_SUBCHAN_WRCACHE_FLUSH 0x00000024 196 196 #define NV10_SUBCHAN_REF_CNT 0x00000050 197 197 #define NVSW_SUBCHAN_PAGE_FLIP 0x00000054
+76
drivers/gpu/drm/nouveau/nouveau_fence.c
··· 33 33 #include "nouveau_dma.h" 34 34 #include "nouveau_fence.h" 35 35 36 + #include <engine/fifo.h> 37 + 36 38 void 37 39 nouveau_fence_context_del(struct nouveau_fence_chan *fctx) 38 40 { ··· 109 107 return !fence->channel; 110 108 } 111 109 110 + struct nouveau_fence_uevent { 111 + struct nouveau_eventh handler; 112 + struct nouveau_fence_priv *priv; 113 + }; 114 + 115 + static int 116 + nouveau_fence_wait_uevent_handler(struct nouveau_eventh *event, int index) 117 + { 118 + struct nouveau_fence_uevent *uevent = 119 + container_of(event, struct nouveau_fence_uevent, handler); 120 + wake_up_all(&uevent->priv->waiting); 121 + return NVKM_EVENT_KEEP; 122 + } 123 + 124 + static int 125 + nouveau_fence_wait_uevent(struct nouveau_fence *fence, bool intr) 126 + 127 + { 128 + struct nouveau_channel *chan = fence->channel; 129 + struct nouveau_fifo *pfifo = nouveau_fifo(chan->drm->device); 130 + struct nouveau_fence_priv *priv = chan->drm->fence; 131 + struct nouveau_fence_uevent uevent = { 132 + .handler.func = nouveau_fence_wait_uevent_handler, 133 + .priv = priv, 134 + }; 135 + int ret = 0; 136 + 137 + nouveau_event_get(pfifo->uevent, 0, &uevent.handler); 138 + 139 + if (fence->timeout) { 140 + unsigned long timeout = fence->timeout - jiffies; 141 + 142 + if (time_before(jiffies, fence->timeout)) { 143 + if (intr) { 144 + ret = wait_event_interruptible_timeout( 145 + priv->waiting, 146 + nouveau_fence_done(fence), 147 + timeout); 148 + } else { 149 + ret = wait_event_timeout(priv->waiting, 150 + nouveau_fence_done(fence), 151 + timeout); 152 + } 153 + } 154 + 155 + if (ret >= 0) { 156 + fence->timeout = jiffies + ret; 157 + if (time_after_eq(jiffies, fence->timeout)) 158 + ret = -EBUSY; 159 + } 160 + } else { 161 + if (intr) { 162 + ret = wait_event_interruptible(priv->waiting, 163 + nouveau_fence_done(fence)); 164 + } else { 165 + wait_event(priv->waiting, nouveau_fence_done(fence)); 166 + } 167 + } 168 + 169 + nouveau_event_put(pfifo->uevent, 0, &uevent.handler); 170 + if (unlikely(ret < 0)) 171 + return ret; 172 + 173 + return 0; 174 + } 175 + 112 176 int 113 177 nouveau_fence_wait(struct nouveau_fence *fence, bool lazy, bool intr) 114 178 { 179 + struct nouveau_channel *chan = fence->channel; 180 + struct nouveau_fence_priv *priv = chan ? chan->drm->fence : NULL; 115 181 unsigned long sleep_time = NSEC_PER_MSEC / 1000; 116 182 ktime_t t; 117 183 int ret = 0; 184 + 185 + while (priv && priv->uevent && lazy && !nouveau_fence_done(fence)) { 186 + ret = nouveau_fence_wait_uevent(fence, intr); 187 + if (ret < 0) 188 + return ret; 189 + } 118 190 119 191 while (!nouveau_fence_done(fence)) { 120 192 if (fence->timeout && time_after_eq(jiffies, fence->timeout)) {
+3
drivers/gpu/drm/nouveau/nouveau_fence.h
··· 43 43 int (*sync)(struct nouveau_fence *, struct nouveau_channel *, 44 44 struct nouveau_channel *); 45 45 u32 (*read)(struct nouveau_channel *); 46 + 47 + wait_queue_head_t waiting; 48 + bool uevent; 46 49 }; 47 50 48 51 #define nouveau_fence(drm) ((struct nouveau_fence_priv *)(drm)->fence)
+6 -2
drivers/gpu/drm/nouveau/nv84_fence.c
··· 47 47 { 48 48 struct nouveau_channel *chan = fence->channel; 49 49 struct nouveau_fifo_chan *fifo = (void *)chan->object; 50 - int ret = RING_SPACE(chan, 7); 50 + int ret = RING_SPACE(chan, 8); 51 51 if (ret == 0) { 52 52 BEGIN_NV04(chan, 0, NV11_SUBCHAN_DMA_SEMAPHORE, 1); 53 53 OUT_RING (chan, NvSema); 54 - BEGIN_NV04(chan, 0, NV84_SUBCHAN_SEMAPHORE_ADDRESS_HIGH, 4); 54 + BEGIN_NV04(chan, 0, NV84_SUBCHAN_SEMAPHORE_ADDRESS_HIGH, 5); 55 55 OUT_RING (chan, upper_32_bits(fifo->chid * 16)); 56 56 OUT_RING (chan, lower_32_bits(fifo->chid * 16)); 57 57 OUT_RING (chan, fence->sequence); 58 58 OUT_RING (chan, NV84_SUBCHAN_SEMAPHORE_TRIGGER_WRITE_LONG); 59 + OUT_RING (chan, 0x00000000); 59 60 FIRE_RING (chan); 60 61 } 61 62 return ret; ··· 174 173 priv->base.emit = nv84_fence_emit; 175 174 priv->base.sync = nv84_fence_sync; 176 175 priv->base.read = nv84_fence_read; 176 + 177 + init_waitqueue_head(&priv->base.waiting); 178 + priv->base.uevent = true; 177 179 178 180 ret = nouveau_gpuobj_new(drm->device, NULL, chan * 16, 0x1000, 0, 179 181 &priv->mem);
+6 -2
drivers/gpu/drm/nouveau/nvc0_fence.c
··· 62 62 u64 addr = fctx->vma.offset + fifo->chid * 16; 63 63 int ret; 64 64 65 - ret = RING_SPACE(chan, 5); 65 + ret = RING_SPACE(chan, 6); 66 66 if (ret == 0) { 67 - BEGIN_NVC0(chan, 0, NV84_SUBCHAN_SEMAPHORE_ADDRESS_HIGH, 4); 67 + BEGIN_NVC0(chan, 0, NV84_SUBCHAN_SEMAPHORE_ADDRESS_HIGH, 5); 68 68 OUT_RING (chan, upper_32_bits(addr)); 69 69 OUT_RING (chan, lower_32_bits(addr)); 70 70 OUT_RING (chan, fence->sequence); 71 71 OUT_RING (chan, NV84_SUBCHAN_SEMAPHORE_TRIGGER_WRITE_LONG); 72 + OUT_RING (chan, 0x00000000); 72 73 FIRE_RING (chan); 73 74 } 74 75 ··· 217 216 priv->base.emit = nvc0_fence_emit; 218 217 priv->base.sync = nvc0_fence_sync; 219 218 priv->base.read = nvc0_fence_read; 219 + 220 + init_waitqueue_head(&priv->base.waiting); 221 + priv->base.uevent = true; 220 222 221 223 ret = nouveau_bo_new(drm->dev, 16 * (pfifo->max + 1), 0, 222 224 TTM_PL_FLAG_VRAM, 0, 0, NULL, &priv->bo);