drm/nouveau: add falcon interrupt handler
authorMaarten Lankhorst <maarten.lankhorst@canonical.com>
Sun, 7 Jul 2013 08:45:43 +0000 (10:45 +0200)
committerBen Skeggs <bskeggs@redhat.com>
Wed, 10 Jul 2013 00:48:07 +0000 (10:48 +1000)
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>
drivers/gpu/drm/nouveau/core/engine/bsp/nvc0.c
drivers/gpu/drm/nouveau/core/engine/bsp/nve0.c
drivers/gpu/drm/nouveau/core/engine/falcon.c
drivers/gpu/drm/nouveau/core/engine/ppp/nvc0.c
drivers/gpu/drm/nouveau/core/engine/vp/nvc0.c
drivers/gpu/drm/nouveau/core/engine/vp/nve0.c
drivers/gpu/drm/nouveau/core/include/engine/falcon.h

index 262c9f5f5f60b322d1a122fe44d99e86d079c818..ce860de43e614a31c73cc6a265a152cbed191233 100644 (file)
@@ -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;
index c46882c8398253ceb1739d82dc31739fef8e09e4..ba6aeca0285ee14afac488166432c5d392ba9a01 100644 (file)
@@ -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;
index 3c7a31f7590edd973b84376427dfeb8d60387b0a..e03fc8e4dc1dac8c8262a93b2b0b812dcae60841 100644 (file)
 #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)
 {
index 98072c1ff3606117e477cb294435e0e75bc11116..73719aaa62d6474ea66fbe85ca252de826f6cff9 100644 (file)
@@ -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;
index 1879229b60eb8ef4e347d16c07f78fed8a8b3f82..ac1f62aace72eb99ff1ca47849aa4828a160a2b5 100644 (file)
@@ -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;
index d28ecbf7bc49ee6c2fd521c6ab652237e04bb6ae..d4c3108479c9344967759c134a9d96802181b8ba 100644 (file)
@@ -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;
index 1edec386ab36008e2a50272c2c2200d4ddb3f80b..181aa7da524dd1c05779f21da4aad367ce4c0e94 100644 (file)
@@ -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);