diff options
Diffstat (limited to 'drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c')
-rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c | 54 |
1 files changed, 31 insertions, 23 deletions
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c index 36a39c7fd8d2..352a0baec84d 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c @@ -54,6 +54,7 @@ gf100_fifo_runlist_commit(struct gf100_fifo *fifo) struct nvkm_device *device = subdev->device; struct nvkm_memory *cur; int nr = 0; + int target; mutex_lock(&subdev->mutex); cur = fifo->runlist.mem[fifo->runlist.active]; @@ -67,7 +68,10 @@ gf100_fifo_runlist_commit(struct gf100_fifo *fifo) } nvkm_done(cur); - nvkm_wr32(device, 0x002270, nvkm_memory_addr(cur) >> 12); + target = (nvkm_memory_target(cur) == NVKM_MEM_TARGET_HOST) ? 0x3 : 0x0; + + nvkm_wr32(device, 0x002270, (nvkm_memory_addr(cur) >> 12) | + (target << 28)); nvkm_wr32(device, 0x002274, 0x01f00000 | nr); if (wait_event_timeout(fifo->runlist.wait, @@ -130,9 +134,9 @@ gf100_fifo_engine(struct gf100_fifo *fifo, u32 engn) } static void -gf100_fifo_recover_work(struct work_struct *work) +gf100_fifo_recover_work(struct work_struct *w) { - struct gf100_fifo *fifo = container_of(work, typeof(*fifo), fault); + struct gf100_fifo *fifo = container_of(w, typeof(*fifo), recover.work); struct nvkm_device *device = fifo->base.engine.subdev.device; struct nvkm_engine *engine; unsigned long flags; @@ -140,15 +144,15 @@ gf100_fifo_recover_work(struct work_struct *work) u64 mask, todo; spin_lock_irqsave(&fifo->base.lock, flags); - mask = fifo->mask; - fifo->mask = 0ULL; + mask = fifo->recover.mask; + fifo->recover.mask = 0ULL; spin_unlock_irqrestore(&fifo->base.lock, flags); - for (todo = mask; engn = __ffs64(todo), todo; todo &= ~(1 << engn)) + for (todo = mask; engn = __ffs64(todo), todo; todo &= ~BIT_ULL(engn)) engm |= 1 << gf100_fifo_engidx(fifo, engn); nvkm_mask(device, 0x002630, engm, engm); - for (todo = mask; engn = __ffs64(todo), todo; todo &= ~(1 << engn)) { + for (todo = mask; engn = __ffs64(todo), todo; todo &= ~BIT_ULL(engn)) { if ((engine = nvkm_device_engine(device, engn))) { nvkm_subdev_fini(&engine->subdev, false); WARN_ON(nvkm_subdev_init(&engine->subdev)); @@ -176,8 +180,8 @@ gf100_fifo_recover(struct gf100_fifo *fifo, struct nvkm_engine *engine, list_del_init(&chan->head); chan->killed = true; - fifo->mask |= 1ULL << engine->subdev.index; - schedule_work(&fifo->fault); + fifo->recover.mask |= 1ULL << engine->subdev.index; + schedule_work(&fifo->recover.work); } static const struct nvkm_enum @@ -330,7 +334,7 @@ gf100_fifo_intr_fault(struct gf100_fifo *fifo, int unit) snprintf(gpcid, sizeof(gpcid), "GPC%d/", gpc); } - if (eu) { + if (eu && eu->data2) { switch (eu->data2) { case NVKM_SUBDEV_BAR: nvkm_mask(device, 0x001704, 0x00000000, 0x00000000); @@ -544,9 +548,16 @@ static int gf100_fifo_oneinit(struct nvkm_fifo *base) { struct gf100_fifo *fifo = gf100_fifo(base); - struct nvkm_device *device = fifo->base.engine.subdev.device; + struct nvkm_subdev *subdev = &fifo->base.engine.subdev; + struct nvkm_device *device = subdev->device; int ret; + /* Determine number of PBDMAs by checking valid enable bits. */ + nvkm_wr32(device, 0x002204, 0xffffffff); + fifo->pbdma_nr = hweight32(nvkm_rd32(device, 0x002204)); + nvkm_debug(subdev, "%d PBDMA(s)\n", fifo->pbdma_nr); + + ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, 0x1000, 0x1000, false, &fifo->runlist.mem[0]); if (ret) @@ -576,25 +587,22 @@ static void gf100_fifo_fini(struct nvkm_fifo *base) { struct gf100_fifo *fifo = gf100_fifo(base); - flush_work(&fifo->fault); + flush_work(&fifo->recover.work); } static void gf100_fifo_init(struct nvkm_fifo *base) { struct gf100_fifo *fifo = gf100_fifo(base); - struct nvkm_subdev *subdev = &fifo->base.engine.subdev; - struct nvkm_device *device = subdev->device; + struct nvkm_device *device = fifo->base.engine.subdev.device; int i; - nvkm_wr32(device, 0x000204, 0xffffffff); - nvkm_wr32(device, 0x002204, 0xffffffff); - - fifo->spoon_nr = hweight32(nvkm_rd32(device, 0x002204)); - nvkm_debug(subdev, "%d PBDMA unit(s)\n", fifo->spoon_nr); + /* Enable PBDMAs. */ + nvkm_wr32(device, 0x000204, (1 << fifo->pbdma_nr) - 1); + nvkm_wr32(device, 0x002204, (1 << fifo->pbdma_nr) - 1); - /* assign engines to PBDMAs */ - if (fifo->spoon_nr >= 3) { + /* Assign engines to PBDMAs. */ + if (fifo->pbdma_nr >= 3) { nvkm_wr32(device, 0x002208, ~(1 << 0)); /* PGRAPH */ nvkm_wr32(device, 0x00220c, ~(1 << 1)); /* PVP */ nvkm_wr32(device, 0x002210, ~(1 << 1)); /* PMSPP */ @@ -604,7 +612,7 @@ gf100_fifo_init(struct nvkm_fifo *base) } /* PBDMA[n] */ - for (i = 0; i < fifo->spoon_nr; i++) { + for (i = 0; i < fifo->pbdma_nr; i++) { nvkm_mask(device, 0x04013c + (i * 0x2000), 0x10000100, 0x00000000); nvkm_wr32(device, 0x040108 + (i * 0x2000), 0xffffffff); /* INTR */ nvkm_wr32(device, 0x04010c + (i * 0x2000), 0xfffffeff); /* INTREN */ @@ -652,7 +660,7 @@ gf100_fifo_new(struct nvkm_device *device, int index, struct nvkm_fifo **pfifo) if (!(fifo = kzalloc(sizeof(*fifo), GFP_KERNEL))) return -ENOMEM; INIT_LIST_HEAD(&fifo->chan); - INIT_WORK(&fifo->fault, gf100_fifo_recover_work); + INIT_WORK(&fifo->recover.work, gf100_fifo_recover_work); *pfifo = &fifo->base; return nvkm_fifo_ctor(&gf100_fifo, device, index, 128, &fifo->base); |