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