summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMaarten Lankhorst <maarten.lankhorst@canonical.com>2013-07-07 10:45:43 +0200
committerBen Skeggs <bskeggs@redhat.com>2013-07-29 13:08:41 +1000
commita0c067448afabd38d4d7b8250e308aa5125ebb94 (patch)
tree06e1eb3cb266045a974200952f5b8166c6a754dd
parent3beec8f97e8546ff3a714877ab612b36f117fa58 (diff)
core: add falcon interrupt handler
This prevents 100% cpu usage on fermi cards when the exit interrupt from the secret scrubber is not acked. Signed-off-by: Maarten Lankhorst <maarten.lankhorst@canonical.com> Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
-rw-r--r--nvkm/engine/bsp/nvc0.c1
-rw-r--r--nvkm/engine/bsp/nve0.c1
-rw-r--r--nvkm/engine/falcon.c19
-rw-r--r--nvkm/engine/ppp/nvc0.c1
-rw-r--r--nvkm/engine/vp/nvc0.c1
-rw-r--r--nvkm/engine/vp/nve0.c1
-rw-r--r--nvkm/include/engine/falcon.h2
7 files changed, 26 insertions, 0 deletions
diff --git a/nvkm/engine/bsp/nvc0.c b/nvkm/engine/bsp/nvc0.c
index 262c9f5f..ce860de4 100644
--- a/nvkm/engine/bsp/nvc0.c
+++ b/nvkm/engine/bsp/nvc0.c
@@ -90,6 +90,7 @@ nvc0_bsp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
return ret;
nv_subdev(priv)->unit = 0x00008000;
+ nv_subdev(priv)->intr = nouveau_falcon_intr;
nv_engine(priv)->cclass = &nvc0_bsp_cclass;
nv_engine(priv)->sclass = nvc0_bsp_sclass;
return 0;
diff --git a/nvkm/engine/bsp/nve0.c b/nvkm/engine/bsp/nve0.c
index c46882c8..ba6aeca0 100644
--- a/nvkm/engine/bsp/nve0.c
+++ b/nvkm/engine/bsp/nve0.c
@@ -90,6 +90,7 @@ nve0_bsp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
return ret;
nv_subdev(priv)->unit = 0x00008000;
+ nv_subdev(priv)->intr = nouveau_falcon_intr;
nv_engine(priv)->cclass = &nve0_bsp_cclass;
nv_engine(priv)->sclass = nve0_bsp_sclass;
return 0;
diff --git a/nvkm/engine/falcon.c b/nvkm/engine/falcon.c
index 3c7a31f7..e03fc8e4 100644
--- a/nvkm/engine/falcon.c
+++ b/nvkm/engine/falcon.c
@@ -23,6 +23,25 @@
#include <engine/falcon.h>
#include <subdev/timer.h>
+void
+nouveau_falcon_intr(struct nouveau_subdev *subdev)
+{
+ struct nouveau_falcon *falcon = (void *)subdev;
+ u32 dispatch = nv_ro32(falcon, 0x01c);
+ u32 intr = nv_ro32(falcon, 0x008) & dispatch & ~(dispatch >> 16);
+
+ if (intr & 0x00000010) {
+ nv_debug(falcon, "ucode halted\n");
+ nv_wo32(falcon, 0x004, 0x00000010);
+ intr &= ~0x00000010;
+ }
+
+ if (intr) {
+ nv_error(falcon, "unhandled intr 0x%08x\n", intr);
+ nv_wo32(falcon, 0x004, intr);
+ }
+}
+
u32
_nouveau_falcon_rd32(struct nouveau_object *object, u64 addr)
{
diff --git a/nvkm/engine/ppp/nvc0.c b/nvkm/engine/ppp/nvc0.c
index 98072c1f..73719aaa 100644
--- a/nvkm/engine/ppp/nvc0.c
+++ b/nvkm/engine/ppp/nvc0.c
@@ -90,6 +90,7 @@ nvc0_ppp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
return ret;
nv_subdev(priv)->unit = 0x00000002;
+ nv_subdev(priv)->intr = nouveau_falcon_intr;
nv_engine(priv)->cclass = &nvc0_ppp_cclass;
nv_engine(priv)->sclass = nvc0_ppp_sclass;
return 0;
diff --git a/nvkm/engine/vp/nvc0.c b/nvkm/engine/vp/nvc0.c
index 1879229b..ac1f62aa 100644
--- a/nvkm/engine/vp/nvc0.c
+++ b/nvkm/engine/vp/nvc0.c
@@ -90,6 +90,7 @@ nvc0_vp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
return ret;
nv_subdev(priv)->unit = 0x00020000;
+ nv_subdev(priv)->intr = nouveau_falcon_intr;
nv_engine(priv)->cclass = &nvc0_vp_cclass;
nv_engine(priv)->sclass = nvc0_vp_sclass;
return 0;
diff --git a/nvkm/engine/vp/nve0.c b/nvkm/engine/vp/nve0.c
index d28ecbf7..d4c31084 100644
--- a/nvkm/engine/vp/nve0.c
+++ b/nvkm/engine/vp/nve0.c
@@ -90,6 +90,7 @@ nve0_vp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
return ret;
nv_subdev(priv)->unit = 0x00020000;
+ nv_subdev(priv)->intr = nouveau_falcon_intr;
nv_engine(priv)->cclass = &nve0_vp_cclass;
nv_engine(priv)->sclass = nve0_vp_sclass;
return 0;
diff --git a/nvkm/include/engine/falcon.h b/nvkm/include/engine/falcon.h
index 1edec386..181aa7da 100644
--- a/nvkm/include/engine/falcon.h
+++ b/nvkm/include/engine/falcon.h
@@ -72,6 +72,8 @@ int nouveau_falcon_create_(struct nouveau_object *, struct nouveau_object *,
struct nouveau_oclass *, u32, bool, const char *,
const char *, int, void **);
+void nouveau_falcon_intr(struct nouveau_subdev *subdev);
+
#define _nouveau_falcon_dtor _nouveau_engine_dtor
int _nouveau_falcon_init(struct nouveau_object *);
int _nouveau_falcon_fini(struct nouveau_object *, bool);