Marcin Slusarz
2012-Apr-25 21:20 UTC
[Nouveau] [PATCH v2 2/4] drm/nouveau: propagate errors from vm flushes
We need this for lockup recovery. Signed-off-by: Marcin Slusarz <marcin.slusarz at gmail.com> --- drivers/gpu/drm/nouveau/nouveau_bo.c | 9 +++++++-- drivers/gpu/drm/nouveau/nouveau_drv.h | 6 +++--- drivers/gpu/drm/nouveau/nouveau_vm.c | 20 ++++++++++---------- drivers/gpu/drm/nouveau/nouveau_vm.h | 18 +++++++++--------- drivers/gpu/drm/nouveau/nv50_fifo.c | 4 ++-- drivers/gpu/drm/nouveau/nv50_graph.c | 12 ++++++++---- drivers/gpu/drm/nouveau/nv50_mpeg.c | 4 ++-- drivers/gpu/drm/nouveau/nv50_vm.c | 30 ++++++++++++++++++++---------- drivers/gpu/drm/nouveau/nv84_crypt.c | 4 ++-- drivers/gpu/drm/nouveau/nva3_copy.c | 4 ++-- drivers/gpu/drm/nouveau/nvc0_vm.c | 3 ++- 11 files changed, 67 insertions(+), 47 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index 638ae32..5b0dc50 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c @@ -1230,10 +1230,15 @@ nouveau_bo_vma_add(struct nouveau_bo *nvbo, struct nouveau_vm *vm, return ret; if (nvbo->bo.mem.mem_type == TTM_PL_VRAM) - nouveau_vm_map(vma, nvbo->bo.mem.mm_node); + ret = nouveau_vm_map(vma, nvbo->bo.mem.mm_node); else if (nvbo->bo.mem.mem_type == TTM_PL_TT) - nouveau_vm_map_sg(vma, 0, size, node); + ret = nouveau_vm_map_sg(vma, 0, size, node); + + if (ret) { + nouveau_vm_put(vma); + return ret; + } list_add_tail(&vma->head, &nvbo->vma_list); vma->refcount = 1; diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h index 2f8e80a..d120baf 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.h +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h @@ -320,7 +320,7 @@ struct nouveau_exec_engine { int (*object_new)(struct nouveau_channel *, int engine, u32 handle, u16 class); void (*set_tile_region)(struct drm_device *dev, int i); - void (*tlb_flush)(struct drm_device *, int engine); + int (*tlb_flush)(struct drm_device *, int engine); }; struct nouveau_instmem_engine { @@ -387,7 +387,7 @@ struct nouveau_fifo_engine { void (*destroy_context)(struct nouveau_channel *); int (*load_context)(struct nouveau_channel *); int (*unload_context)(struct drm_device *); - void (*tlb_flush)(struct drm_device *dev); + int (*tlb_flush)(struct drm_device *dev); }; struct nouveau_display_engine { @@ -1246,7 +1246,7 @@ extern int nv50_fifo_create_context(struct nouveau_channel *); extern void nv50_fifo_destroy_context(struct nouveau_channel *); extern int nv50_fifo_load_context(struct nouveau_channel *); extern int nv50_fifo_unload_context(struct drm_device *); -extern void nv50_fifo_tlb_flush(struct drm_device *dev); +extern int nv50_fifo_tlb_flush(struct drm_device *dev); /* nvc0_fifo.c */ extern int nvc0_fifo_init(struct drm_device *); diff --git a/drivers/gpu/drm/nouveau/nouveau_vm.c b/drivers/gpu/drm/nouveau/nouveau_vm.c index 2bf6c03..e2d4853 100644 --- a/drivers/gpu/drm/nouveau/nouveau_vm.c +++ b/drivers/gpu/drm/nouveau/nouveau_vm.c @@ -27,7 +27,7 @@ #include "nouveau_mm.h" #include "nouveau_vm.h" -void +int nouveau_vm_map_at(struct nouveau_vma *vma, u64 delta, struct nouveau_mem *node) { struct nouveau_vm *vm = vma->vm; @@ -67,16 +67,16 @@ nouveau_vm_map_at(struct nouveau_vma *vma, u64 delta, struct nouveau_mem *node) } } - vm->flush(vm); + return vm->flush(vm); } -void +int nouveau_vm_map(struct nouveau_vma *vma, struct nouveau_mem *node) { - nouveau_vm_map_at(vma, 0, node); + return nouveau_vm_map_at(vma, 0, node); } -void +int nouveau_vm_map_sg(struct nouveau_vma *vma, u64 delta, u64 length, struct nouveau_mem *mem) { @@ -110,10 +110,10 @@ nouveau_vm_map_sg(struct nouveau_vma *vma, u64 delta, u64 length, } } - vm->flush(vm); + return vm->flush(vm); } -void +int nouveau_vm_unmap_at(struct nouveau_vma *vma, u64 delta, u64 length) { struct nouveau_vm *vm = vma->vm; @@ -144,13 +144,13 @@ nouveau_vm_unmap_at(struct nouveau_vma *vma, u64 delta, u64 length) } } - vm->flush(vm); + return vm->flush(vm); } -void +int nouveau_vm_unmap(struct nouveau_vma *vma) { - nouveau_vm_unmap_at(vma, 0, (u64)vma->node->length << 12); + return nouveau_vm_unmap_at(vma, 0, (u64)vma->node->length << 12); } static void diff --git a/drivers/gpu/drm/nouveau/nouveau_vm.h b/drivers/gpu/drm/nouveau/nouveau_vm.h index 4fb6e72..59dc206 100644 --- a/drivers/gpu/drm/nouveau/nouveau_vm.h +++ b/drivers/gpu/drm/nouveau/nouveau_vm.h @@ -73,7 +73,7 @@ struct nouveau_vm { void (*map_sg)(struct nouveau_vma *, struct nouveau_gpuobj *, struct nouveau_mem *, u32 pte, u32 cnt, dma_addr_t *); void (*unmap)(struct nouveau_gpuobj *pgt, u32 pte, u32 cnt); - void (*flush)(struct nouveau_vm *); + int (*flush)(struct nouveau_vm *); }; /* nouveau_vm.c */ @@ -84,11 +84,11 @@ int nouveau_vm_ref(struct nouveau_vm *, struct nouveau_vm **, int nouveau_vm_get(struct nouveau_vm *, u64 size, u32 page_shift, u32 access, struct nouveau_vma *); void nouveau_vm_put(struct nouveau_vma *); -void nouveau_vm_map(struct nouveau_vma *, struct nouveau_mem *); -void nouveau_vm_map_at(struct nouveau_vma *, u64 offset, struct nouveau_mem *); -void nouveau_vm_unmap(struct nouveau_vma *); -void nouveau_vm_unmap_at(struct nouveau_vma *, u64 offset, u64 length); -void nouveau_vm_map_sg(struct nouveau_vma *, u64 offset, u64 length, +int nouveau_vm_map(struct nouveau_vma *, struct nouveau_mem *); +int nouveau_vm_map_at(struct nouveau_vma *, u64 offset, struct nouveau_mem *); +int nouveau_vm_unmap(struct nouveau_vma *); +int nouveau_vm_unmap_at(struct nouveau_vma *, u64 offset, u64 length); +int nouveau_vm_map_sg(struct nouveau_vma *, u64 offset, u64 length, struct nouveau_mem *); /* nv50_vm.c */ @@ -99,8 +99,8 @@ void nv50_vm_map(struct nouveau_vma *, struct nouveau_gpuobj *, void nv50_vm_map_sg(struct nouveau_vma *, struct nouveau_gpuobj *, struct nouveau_mem *, u32 pte, u32 cnt, dma_addr_t *); void nv50_vm_unmap(struct nouveau_gpuobj *, u32 pte, u32 cnt); -void nv50_vm_flush(struct nouveau_vm *); -void nv50_vm_flush_engine(struct drm_device *, int engine); +int nv50_vm_flush(struct nouveau_vm *); +int nv50_vm_flush_engine(struct drm_device *, int engine); /* nvc0_vm.c */ void nvc0_vm_map_pgt(struct nouveau_gpuobj *pgd, u32 pde, @@ -110,6 +110,6 @@ void nvc0_vm_map(struct nouveau_vma *, struct nouveau_gpuobj *, void nvc0_vm_map_sg(struct nouveau_vma *, struct nouveau_gpuobj *, struct nouveau_mem *, u32 pte, u32 cnt, dma_addr_t *); void nvc0_vm_unmap(struct nouveau_gpuobj *, u32 pte, u32 cnt); -void nvc0_vm_flush(struct nouveau_vm *); +int nvc0_vm_flush(struct nouveau_vm *); #endif diff --git a/drivers/gpu/drm/nouveau/nv50_fifo.c b/drivers/gpu/drm/nouveau/nv50_fifo.c index 3bc2a56..3438fc2 100644 --- a/drivers/gpu/drm/nouveau/nv50_fifo.c +++ b/drivers/gpu/drm/nouveau/nv50_fifo.c @@ -499,8 +499,8 @@ nv50_fifo_unload_context(struct drm_device *dev) return 0; } -void +int nv50_fifo_tlb_flush(struct drm_device *dev) { - nv50_vm_flush_engine(dev, 5); + return nv50_vm_flush_engine(dev, 5); } diff --git a/drivers/gpu/drm/nouveau/nv50_graph.c b/drivers/gpu/drm/nouveau/nv50_graph.c index 2698d80..6899547 100644 --- a/drivers/gpu/drm/nouveau/nv50_graph.c +++ b/drivers/gpu/drm/nouveau/nv50_graph.c @@ -397,13 +397,13 @@ nv50_graph_nvsw_mthd_page_flip(struct nouveau_channel *chan, } -static void +static int nv50_graph_tlb_flush(struct drm_device *dev, int engine) { - nv50_vm_flush_engine(dev, 0); + return nv50_vm_flush_engine(dev, 0); } -static void +static int nv84_graph_tlb_flush(struct drm_device *dev, int engine) { struct drm_nouveau_private *dev_priv = dev->dev_private; @@ -412,6 +412,7 @@ nv84_graph_tlb_flush(struct drm_device *dev, int engine) unsigned long flags; u64 start; u32 tmp; + int ret = 0; spin_lock_irqsave(&dev_priv->context_switch_lock, flags); nv_mask(dev, 0x400500, 0x00000001, 0x00000000); @@ -441,12 +442,15 @@ nv84_graph_tlb_flush(struct drm_device *dev, int engine) "0x%08x 0x%08x 0x%08x 0x%08x\n", nv_rd32(dev, 0x400700), nv_rd32(dev, 0x400380), nv_rd32(dev, 0x400384), nv_rd32(dev, 0x400388)); + ret = -EIO; } - nv50_vm_flush_engine(dev, 0); + if (!ret) + ret = nv50_vm_flush_engine(dev, 0); nv_mask(dev, 0x400500, 0x00000001, 0x00000001); spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); + return ret; } static struct nouveau_enum nv50_mp_exec_error_names[] = { diff --git a/drivers/gpu/drm/nouveau/nv50_mpeg.c b/drivers/gpu/drm/nouveau/nv50_mpeg.c index b57a2d1..1730611 100644 --- a/drivers/gpu/drm/nouveau/nv50_mpeg.c +++ b/drivers/gpu/drm/nouveau/nv50_mpeg.c @@ -128,10 +128,10 @@ nv50_mpeg_object_new(struct nouveau_channel *chan, int engine, return ret; } -static void +static int nv50_mpeg_tlb_flush(struct drm_device *dev, int engine) { - nv50_vm_flush_engine(dev, 0x08); + return nv50_vm_flush_engine(dev, 0x08); } static int diff --git a/drivers/gpu/drm/nouveau/nv50_vm.c b/drivers/gpu/drm/nouveau/nv50_vm.c index 44fbac9..6b8df85 100644 --- a/drivers/gpu/drm/nouveau/nv50_vm.c +++ b/drivers/gpu/drm/nouveau/nv50_vm.c @@ -142,38 +142,48 @@ nv50_vm_unmap(struct nouveau_gpuobj *pgt, u32 pte, u32 cnt) } } -void +int nv50_vm_flush(struct nouveau_vm *vm) { struct drm_nouveau_private *dev_priv = vm->dev->dev_private; struct nouveau_instmem_engine *pinstmem = &dev_priv->engine.instmem; struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo; int i; + int ret; pinstmem->flush(vm->dev); /* BAR */ - if (vm == dev_priv->bar1_vm || vm == dev_priv->bar3_vm) { - nv50_vm_flush_engine(vm->dev, 6); - return; - } + if (vm == dev_priv->bar1_vm || vm == dev_priv->bar3_vm) + return nv50_vm_flush_engine(vm->dev, 6); + + ret = pfifo->tlb_flush(vm->dev); + if (ret) + return ret; - pfifo->tlb_flush(vm->dev); for (i = 0; i < NVOBJ_ENGINE_NR; i++) { - if (atomic_read(&vm->engref[i])) - dev_priv->eng[i]->tlb_flush(vm->dev, i); + if (atomic_read(&vm->engref[i])) { + ret = dev_priv->eng[i]->tlb_flush(vm->dev, i); + if (ret) + break; + } } + return ret; } -void +int nv50_vm_flush_engine(struct drm_device *dev, int engine) { struct drm_nouveau_private *dev_priv = dev->dev_private; unsigned long flags; + int ret = 0; spin_lock_irqsave(&dev_priv->vm_lock, flags); nv_wr32(dev, 0x100c80, (engine << 16) | 1); - if (!nv_wait(dev, 0x100c80, 0x00000001, 0x00000000)) + if (!nv_wait(dev, 0x100c80, 0x00000001, 0x00000000)) { NV_ERROR(dev, "vm flush timeout: engine %d\n", engine); + ret = -EIO; + } spin_unlock_irqrestore(&dev_priv->vm_lock, flags); + return ret; } diff --git a/drivers/gpu/drm/nouveau/nv84_crypt.c b/drivers/gpu/drm/nouveau/nv84_crypt.c index edece9c..6b8b78e 100644 --- a/drivers/gpu/drm/nouveau/nv84_crypt.c +++ b/drivers/gpu/drm/nouveau/nv84_crypt.c @@ -111,10 +111,10 @@ nv84_crypt_object_new(struct nouveau_channel *chan, int engine, return ret; } -static void +static int nv84_crypt_tlb_flush(struct drm_device *dev, int engine) { - nv50_vm_flush_engine(dev, 0x0a); + return nv50_vm_flush_engine(dev, 0x0a); } static void diff --git a/drivers/gpu/drm/nouveau/nva3_copy.c b/drivers/gpu/drm/nouveau/nva3_copy.c index 8f356d5..c116e73 100644 --- a/drivers/gpu/drm/nouveau/nva3_copy.c +++ b/drivers/gpu/drm/nouveau/nva3_copy.c @@ -105,10 +105,10 @@ nva3_copy_context_del(struct nouveau_channel *chan, int engine) chan->engctx[engine] = ctx; } -static void +static int nva3_copy_tlb_flush(struct drm_device *dev, int engine) { - nv50_vm_flush_engine(dev, 0x0d); + return nv50_vm_flush_engine(dev, 0x0d); } static int diff --git a/drivers/gpu/drm/nouveau/nvc0_vm.c b/drivers/gpu/drm/nouveau/nvc0_vm.c index 30d2bd5..1f6fbff 100644 --- a/drivers/gpu/drm/nouveau/nvc0_vm.c +++ b/drivers/gpu/drm/nouveau/nvc0_vm.c @@ -99,7 +99,7 @@ nvc0_vm_unmap(struct nouveau_gpuobj *pgt, u32 pte, u32 cnt) } } -void +int nvc0_vm_flush(struct nouveau_vm *vm) { struct drm_nouveau_private *dev_priv = vm->dev->dev_private; @@ -133,4 +133,5 @@ nvc0_vm_flush(struct nouveau_vm *vm) } } spin_unlock_irqrestore(&dev_priv->vm_lock, flags); + return 0; } -- 1.7.8.5
Marcin Slusarz
2012-May-27 19:39 UTC
[Nouveau] [PATCH v2 2/4] drm/nouveau: propagate errors from vm flushes
From: Marcin Slusarz <marcin.slusarz at gmail.com> Subject: [PATCH v3] drm/nouveau: propagate errors from vm flushes Signed-off-by: Marcin Slusarz <marcin.slusarz at gmail.com> --- v3: rebased on top of current nouveau-git --- drivers/gpu/drm/nouveau/nouveau_bo.c | 9 +++++++-- drivers/gpu/drm/nouveau/nouveau_drv.h | 2 +- drivers/gpu/drm/nouveau/nouveau_fifo.h | 2 +- drivers/gpu/drm/nouveau/nouveau_vm.c | 20 ++++++++++---------- drivers/gpu/drm/nouveau/nouveau_vm.h | 20 ++++++++++---------- drivers/gpu/drm/nouveau/nv50_fifo.c | 4 ++-- drivers/gpu/drm/nouveau/nv50_graph.c | 12 ++++++++---- drivers/gpu/drm/nouveau/nv50_mpeg.c | 4 ++-- drivers/gpu/drm/nouveau/nv50_vm.c | 16 ++++++++++++---- drivers/gpu/drm/nouveau/nv84_crypt.c | 4 ++-- drivers/gpu/drm/nouveau/nv98_crypt.c | 4 ++-- drivers/gpu/drm/nouveau/nva3_copy.c | 4 ++-- drivers/gpu/drm/nouveau/nvc0_vm.c | 14 +++++++++++--- 13 files changed, 70 insertions(+), 45 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index ab15f5e..f30a75a 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c @@ -1427,10 +1427,15 @@ nouveau_bo_vma_add(struct nouveau_bo *nvbo, struct nouveau_vm *vm, return ret; if (nvbo->bo.mem.mem_type == TTM_PL_VRAM) - nouveau_vm_map(vma, nvbo->bo.mem.mm_node); + ret = nouveau_vm_map(vma, nvbo->bo.mem.mm_node); else if (nvbo->bo.mem.mem_type == TTM_PL_TT) - nouveau_vm_map_sg(vma, 0, size, node); + ret = nouveau_vm_map_sg(vma, 0, size, node); + + if (ret) { + nouveau_vm_put(vma); + return ret; + } list_add_tail(&vma->head, &nvbo->vma_list); vma->refcount = 1; diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h index b800c79..c1539b5 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.h +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h @@ -125,7 +125,7 @@ struct nouveau_engine { int (*object_new)(struct nouveau_channel *, int engine, u32 handle, u16 class); void (*set_tile_region)(struct nouveau_device *, int i); - void (*tlb_flush)(struct nouveau_device *, int engine); + int (*tlb_flush)(struct nouveau_device *, int engine); }; #define nouveau_engine_create(ndev,engine,sstr,fstr,data) \ diff --git a/drivers/gpu/drm/nouveau/nouveau_fifo.h b/drivers/gpu/drm/nouveau/nouveau_fifo.h index 13a96ef..c2fb136 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fifo.h +++ b/drivers/gpu/drm/nouveau/nouveau_fifo.h @@ -20,7 +20,7 @@ void nv04_fifo_ramht(struct nouveau_device *, struct nouveau_ramht **); void nv50_fifo_playlist_update(struct nouveau_device *); void nv50_fifo_destroy(struct nouveau_device *, int); -void nv50_fifo_tlb_flush(struct nouveau_device *, int); +int nv50_fifo_tlb_flush(struct nouveau_device *, int); int nv04_fifo_create(struct nouveau_device *, int engine); int nv10_fifo_create(struct nouveau_device *, int engine); diff --git a/drivers/gpu/drm/nouveau/nouveau_vm.c b/drivers/gpu/drm/nouveau/nouveau_vm.c index 2678a0b7..e3cd453 100644 --- a/drivers/gpu/drm/nouveau/nouveau_vm.c +++ b/drivers/gpu/drm/nouveau/nouveau_vm.c @@ -29,7 +29,7 @@ #include "nouveau_vm.h" #include "nouveau_gpuobj.h" -void +int nouveau_vm_map_at(struct nouveau_vma *vma, u64 delta, struct nouveau_mem *node) { struct nouveau_vm *vm = vma->vm; @@ -69,16 +69,16 @@ nouveau_vm_map_at(struct nouveau_vma *vma, u64 delta, struct nouveau_mem *node) } } - vm->flush(vm); + return vm->flush(vm); } -void +int nouveau_vm_map(struct nouveau_vma *vma, struct nouveau_mem *node) { - nouveau_vm_map_at(vma, 0, node); + return nouveau_vm_map_at(vma, 0, node); } -void +int nouveau_vm_map_sg(struct nouveau_vma *vma, u64 delta, u64 length, struct nouveau_mem *mem) { @@ -112,10 +112,10 @@ nouveau_vm_map_sg(struct nouveau_vma *vma, u64 delta, u64 length, } } - vm->flush(vm); + return vm->flush(vm); } -void +int nouveau_vm_unmap_at(struct nouveau_vma *vma, u64 delta, u64 length) { struct nouveau_vm *vm = vma->vm; @@ -146,13 +146,13 @@ nouveau_vm_unmap_at(struct nouveau_vma *vma, u64 delta, u64 length) } } - vm->flush(vm); + return vm->flush(vm); } -void +int nouveau_vm_unmap(struct nouveau_vma *vma) { - nouveau_vm_unmap_at(vma, 0, (u64)vma->node->length << 12); + return nouveau_vm_unmap_at(vma, 0, (u64)vma->node->length << 12); } static void diff --git a/drivers/gpu/drm/nouveau/nouveau_vm.h b/drivers/gpu/drm/nouveau/nouveau_vm.h index 93a975e..f3bd0a5 100644 --- a/drivers/gpu/drm/nouveau/nouveau_vm.h +++ b/drivers/gpu/drm/nouveau/nouveau_vm.h @@ -73,7 +73,7 @@ struct nouveau_vm { void (*map_sg)(struct nouveau_vma *, struct nouveau_gpuobj *, struct nouveau_mem *, u32 pte, u32 cnt, dma_addr_t *); void (*unmap)(struct nouveau_gpuobj *pgt, u32 pte, u32 cnt); - void (*flush)(struct nouveau_vm *); + int (*flush)(struct nouveau_vm *); }; /* nouveau_vm.c */ @@ -84,11 +84,11 @@ int nouveau_vm_ref(struct nouveau_vm *, struct nouveau_vm **, int nouveau_vm_get(struct nouveau_vm *, u64 size, u32 page_shift, u32 access, struct nouveau_vma *); void nouveau_vm_put(struct nouveau_vma *); -void nouveau_vm_map(struct nouveau_vma *, struct nouveau_mem *); -void nouveau_vm_map_at(struct nouveau_vma *, u64 offset, struct nouveau_mem *); -void nouveau_vm_unmap(struct nouveau_vma *); -void nouveau_vm_unmap_at(struct nouveau_vma *, u64 offset, u64 length); -void nouveau_vm_map_sg(struct nouveau_vma *, u64 offset, u64 length, +int nouveau_vm_map(struct nouveau_vma *, struct nouveau_mem *); +int nouveau_vm_map_at(struct nouveau_vma *, u64 offset, struct nouveau_mem *); +int nouveau_vm_unmap(struct nouveau_vma *); +int nouveau_vm_unmap_at(struct nouveau_vma *, u64 offset, u64 length); +int nouveau_vm_map_sg(struct nouveau_vma *, u64 offset, u64 length, struct nouveau_mem *); /* nv50_vm.c */ @@ -99,8 +99,8 @@ void nv50_vm_map(struct nouveau_vma *, struct nouveau_gpuobj *, void nv50_vm_map_sg(struct nouveau_vma *, struct nouveau_gpuobj *, struct nouveau_mem *, u32 pte, u32 cnt, dma_addr_t *); void nv50_vm_unmap(struct nouveau_gpuobj *, u32 pte, u32 cnt); -void nv50_vm_flush(struct nouveau_vm *); -void nv50_vm_flush_engine(struct nouveau_device *, int engine); +int nv50_vm_flush(struct nouveau_vm *); +int nv50_vm_flush_engine(struct nouveau_device *, int engine); /* nvc0_vm.c */ void nvc0_vm_map_pgt(struct nouveau_gpuobj *pgd, u32 pde, @@ -110,7 +110,7 @@ void nvc0_vm_map(struct nouveau_vma *, struct nouveau_gpuobj *, void nvc0_vm_map_sg(struct nouveau_vma *, struct nouveau_gpuobj *, struct nouveau_mem *, u32 pte, u32 cnt, dma_addr_t *); void nvc0_vm_unmap(struct nouveau_gpuobj *, u32 pte, u32 cnt); -void nvc0_vm_flush(struct nouveau_vm *); -void nvc0_vm_flush_engine(struct nouveau_device *, u64 addr, u32 type); +int nvc0_vm_flush(struct nouveau_vm *); +int nvc0_vm_flush_engine(struct nouveau_device *, u64 addr, u32 type); #endif diff --git a/drivers/gpu/drm/nouveau/nv50_fifo.c b/drivers/gpu/drm/nouveau/nv50_fifo.c index a59094d..81271ee 100644 --- a/drivers/gpu/drm/nouveau/nv50_fifo.c +++ b/drivers/gpu/drm/nouveau/nv50_fifo.c @@ -229,10 +229,10 @@ nv50_fifo_fini(struct nouveau_device *ndev, int engine, bool suspend) return 0; } -void +int nv50_fifo_tlb_flush(struct nouveau_device *ndev, int engine) { - nv50_vm_flush_engine(ndev, 5); + return nv50_vm_flush_engine(ndev, 5); } void diff --git a/drivers/gpu/drm/nouveau/nv50_graph.c b/drivers/gpu/drm/nouveau/nv50_graph.c index 4fe58eb..78365fe 100644 --- a/drivers/gpu/drm/nouveau/nv50_graph.c +++ b/drivers/gpu/drm/nouveau/nv50_graph.c @@ -205,13 +205,13 @@ nv50_graph_object_new(struct nouveau_channel *chan, int engine, return ret; } -static void +static int nv50_graph_tlb_flush(struct nouveau_device *ndev, int engine) { - nv50_vm_flush_engine(ndev, 0); + return nv50_vm_flush_engine(ndev, 0); } -static void +static int nv84_graph_tlb_flush(struct nouveau_device *ndev, int engine) { struct nouveau_timer *ptimer = nv_subdev(ndev, NVDEV_SUBDEV_TIMER); @@ -219,6 +219,7 @@ nv84_graph_tlb_flush(struct nouveau_device *ndev, int engine) unsigned long flags; u64 start; u32 tmp; + int ret = 0; spin_lock_irqsave(&ndev->context_switch_lock, flags); nv_mask(ndev, 0x400500, 0x00000001, 0x00000000); @@ -249,12 +250,15 @@ nv84_graph_tlb_flush(struct nouveau_device *ndev, int engine) "0x%08x 0x%08x 0x%08x 0x%08x\n", nv_rd32(ndev, 0x400700), nv_rd32(ndev, 0x400380), nv_rd32(ndev, 0x400384), nv_rd32(ndev, 0x400388)); + ret = -EIO; } - nv50_vm_flush_engine(ndev, 0); + if (!ret) + ret = nv50_vm_flush_engine(ndev, 0); nv_mask(ndev, 0x400500, 0x00000001, 0x00000001); spin_unlock_irqrestore(&ndev->context_switch_lock, flags); + return ret; } static struct nouveau_enum nv50_mp_exec_error_names[] = { diff --git a/drivers/gpu/drm/nouveau/nv50_mpeg.c b/drivers/gpu/drm/nouveau/nv50_mpeg.c index 9a0e80b..2f3325c 100644 --- a/drivers/gpu/drm/nouveau/nv50_mpeg.c +++ b/drivers/gpu/drm/nouveau/nv50_mpeg.c @@ -115,10 +115,10 @@ nv50_mpeg_object_new(struct nouveau_channel *chan, int engine, return ret; } -static void +static int nv50_mpeg_tlb_flush(struct nouveau_device *ndev, int engine) { - nv50_vm_flush_engine(ndev, 0x08); + return nv50_vm_flush_engine(ndev, 0x08); } static int diff --git a/drivers/gpu/drm/nouveau/nv50_vm.c b/drivers/gpu/drm/nouveau/nv50_vm.c index a5be4cf..31138b4 100644 --- a/drivers/gpu/drm/nouveau/nv50_vm.c +++ b/drivers/gpu/drm/nouveau/nv50_vm.c @@ -146,30 +146,38 @@ nv50_vm_unmap(struct nouveau_gpuobj *pgt, u32 pte, u32 cnt) } } -void +int nv50_vm_flush(struct nouveau_vm *vm) { struct nouveau_device *ndev = vm->device; int i; + int ret = 0; nouveau_instmem_flush(ndev); for (i = 0; i < NVDEV_SUBDEV_NR; i++) { if (atomic_read(&vm->engref[i])) { struct nouveau_engine *engine = nv_engine(ndev, i); - engine->tlb_flush(ndev, i); + ret = engine->tlb_flush(ndev, i); + if (ret) + break; } } + return ret; } -void +int nv50_vm_flush_engine(struct nouveau_device *ndev, int engine) { unsigned long flags; + int ret = 0; spin_lock_irqsave(&ndev->vm_lock, flags); nv_wr32(ndev, 0x100c80, (engine << 16) | 1); - if (!nv_wait(ndev, 0x100c80, 0x00000001, 0x00000000)) + if (!nv_wait(ndev, 0x100c80, 0x00000001, 0x00000000)) { NV_ERROR(ndev, "vm flush timeout: engine %d\n", engine); + ret = -EIO; + } spin_unlock_irqrestore(&ndev->vm_lock, flags); + return ret; } diff --git a/drivers/gpu/drm/nouveau/nv84_crypt.c b/drivers/gpu/drm/nouveau/nv84_crypt.c index 38dc6fc..6059f0e 100644 --- a/drivers/gpu/drm/nouveau/nv84_crypt.c +++ b/drivers/gpu/drm/nouveau/nv84_crypt.c @@ -114,10 +114,10 @@ nv84_crypt_object_new(struct nouveau_channel *chan, int engine, return ret; } -static void +static int nv84_crypt_tlb_flush(struct nouveau_device *ndev, int engine) { - nv50_vm_flush_engine(ndev, 0x0a); + return nv50_vm_flush_engine(ndev, 0x0a); } static void diff --git a/drivers/gpu/drm/nouveau/nv98_crypt.c b/drivers/gpu/drm/nouveau/nv98_crypt.c index ef2ff44..c42e41c 100644 --- a/drivers/gpu/drm/nouveau/nv98_crypt.c +++ b/drivers/gpu/drm/nouveau/nv98_crypt.c @@ -105,10 +105,10 @@ nv98_crypt_object_new(struct nouveau_channel *chan, int engine, return nouveau_ramht_insert(chan, handle, cctx->mem); } -static void +static int nv98_crypt_tlb_flush(struct nouveau_device *ndev, int engine) { - nv50_vm_flush_engine(ndev, 0x0a); + return nv50_vm_flush_engine(ndev, 0x0a); } static int diff --git a/drivers/gpu/drm/nouveau/nva3_copy.c b/drivers/gpu/drm/nouveau/nva3_copy.c index 87c3580..6e6482f 100644 --- a/drivers/gpu/drm/nouveau/nva3_copy.c +++ b/drivers/gpu/drm/nouveau/nva3_copy.c @@ -95,10 +95,10 @@ nva3_copy_context_del(struct nouveau_channel *chan, int engine) chan->engctx[engine] = ctx; } -static void +static int nva3_copy_tlb_flush(struct nouveau_device *ndev, int engine) { - nv50_vm_flush_engine(ndev, 0x0d); + return nv50_vm_flush_engine(ndev, 0x0d); } static int diff --git a/drivers/gpu/drm/nouveau/nvc0_vm.c b/drivers/gpu/drm/nouveau/nvc0_vm.c index cc7096a..7301a5f 100644 --- a/drivers/gpu/drm/nouveau/nvc0_vm.c +++ b/drivers/gpu/drm/nouveau/nvc0_vm.c @@ -101,10 +101,11 @@ nvc0_vm_unmap(struct nouveau_gpuobj *pgt, u32 pte, u32 cnt) } } -void +int nvc0_vm_flush_engine(struct nouveau_device *ndev, u64 addr, u32 type) { unsigned long flags; + int ret = 0; /* looks like maybe a "free flush slots" counter, the * faster you write to 0x100cbc to more it decreases @@ -113,6 +114,7 @@ nvc0_vm_flush_engine(struct nouveau_device *ndev, u64 addr, u32 type) if (!nv_wait_ne(ndev, 0x100c80, 0x00ff0000, 0x00000000)) { NV_ERROR(ndev, "vm timeout 0: 0x%08x %d\n", nv_rd32(ndev, 0x100c80), type); + ret = -EIO; } nv_wr32(ndev, 0x100cb8, addr >> 8); @@ -122,19 +124,25 @@ nvc0_vm_flush_engine(struct nouveau_device *ndev, u64 addr, u32 type) if (!nv_wait(ndev, 0x100c80, 0x00008000, 0x00008000)) { NV_ERROR(ndev, "vm timeout 1: 0x%08x %d\n", nv_rd32(ndev, 0x100c80), type); + ret = -EIO; } spin_unlock_irqrestore(&ndev->vm_lock, flags); + return ret; } -void +int nvc0_vm_flush(struct nouveau_vm *vm) { struct nouveau_device *ndev = vm->device; struct nouveau_vm_pgd *vpgd; + int ret = 0; nouveau_instmem_flush(ndev); list_for_each_entry(vpgd, &vm->pgd_list, head) { - nvc0_vm_flush_engine(ndev, vpgd->obj->vinst, 1); + ret = nvc0_vm_flush_engine(ndev, vpgd->obj->vinst, 1); + if (ret) + break; } + return ret; } -- 1.7.8.6