Commit 9bd2ddba authored by Ben Skeggs's avatar Ben Skeggs

drm/nouveau/fifo/nvc0-: use interrupt 31 as an event trigger

Generated if you try and use fifo method 0x20 on any subchannel, appears
that it can be safely masked off without stalling the whole GPU.
Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
parent 1d7c71a3
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#include <core/client.h> #include <core/client.h>
#include <core/object.h> #include <core/object.h>
#include <core/handle.h> #include <core/handle.h>
#include <core/event.h>
#include <core/class.h> #include <core/class.h>
#include <engine/dmaobj.h> #include <engine/dmaobj.h>
...@@ -165,6 +166,7 @@ void ...@@ -165,6 +166,7 @@ void
nouveau_fifo_destroy(struct nouveau_fifo *priv) nouveau_fifo_destroy(struct nouveau_fifo *priv)
{ {
kfree(priv->channel); kfree(priv->channel);
nouveau_event_destroy(&priv->uevent);
nouveau_engine_destroy(&priv->base); nouveau_engine_destroy(&priv->base);
} }
...@@ -189,6 +191,10 @@ nouveau_fifo_create_(struct nouveau_object *parent, ...@@ -189,6 +191,10 @@ nouveau_fifo_create_(struct nouveau_object *parent,
if (!priv->channel) if (!priv->channel)
return -ENOMEM; return -ENOMEM;
ret = nouveau_event_create(1, &priv->uevent);
if (ret)
return ret;
priv->chid = nouveau_fifo_chid; priv->chid = nouveau_fifo_chid;
spin_lock_init(&priv->lock); spin_lock_init(&priv->lock);
return 0; return 0;
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include <core/namedb.h> #include <core/namedb.h>
#include <core/gpuobj.h> #include <core/gpuobj.h>
#include <core/engctx.h> #include <core/engctx.h>
#include <core/event.h>
#include <core/class.h> #include <core/class.h>
#include <core/math.h> #include <core/math.h>
#include <core/enum.h> #include <core/enum.h>
...@@ -583,7 +584,8 @@ nvc0_fifo_intr(struct nouveau_subdev *subdev) ...@@ -583,7 +584,8 @@ nvc0_fifo_intr(struct nouveau_subdev *subdev)
if (stat & 0x80000000) { if (stat & 0x80000000) {
u32 intr = nv_mask(priv, 0x0025a8, 0x00000000, 0x00000000); u32 intr = nv_mask(priv, 0x0025a8, 0x00000000, 0x00000000);
nv_warn(priv, "INTR 0x80000000: 0x%08x\n", intr); nouveau_event_trigger(priv->base.uevent, 0);
nv_debug(priv, "INTR 0x80000000: 0x%08x\n", intr);
stat &= ~0x80000000; stat &= ~0x80000000;
} }
...@@ -594,6 +596,20 @@ nvc0_fifo_intr(struct nouveau_subdev *subdev) ...@@ -594,6 +596,20 @@ nvc0_fifo_intr(struct nouveau_subdev *subdev)
} }
} }
static void
nvc0_fifo_uevent_enable(struct nouveau_event *event, int index)
{
struct nvc0_fifo_priv *priv = event->priv;
nv_mask(priv, 0x002140, 0x80000000, 0x80000000);
}
static void
nvc0_fifo_uevent_disable(struct nouveau_event *event, int index)
{
struct nvc0_fifo_priv *priv = event->priv;
nv_mask(priv, 0x002140, 0x80000000, 0x00000000);
}
static int static int
nvc0_fifo_ctor(struct nouveau_object *parent, struct nouveau_object *engine, nvc0_fifo_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
struct nouveau_oclass *oclass, void *data, u32 size, struct nouveau_oclass *oclass, void *data, u32 size,
...@@ -627,6 +643,10 @@ nvc0_fifo_ctor(struct nouveau_object *parent, struct nouveau_object *engine, ...@@ -627,6 +643,10 @@ nvc0_fifo_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
if (ret) if (ret)
return ret; return ret;
priv->base.uevent->enable = nvc0_fifo_uevent_enable;
priv->base.uevent->disable = nvc0_fifo_uevent_disable;
priv->base.uevent->priv = priv;
nv_subdev(priv)->unit = 0x00000100; nv_subdev(priv)->unit = 0x00000100;
nv_subdev(priv)->intr = nvc0_fifo_intr; nv_subdev(priv)->intr = nvc0_fifo_intr;
nv_engine(priv)->cclass = &nvc0_fifo_cclass; nv_engine(priv)->cclass = &nvc0_fifo_cclass;
...@@ -685,7 +705,7 @@ nvc0_fifo_init(struct nouveau_object *object) ...@@ -685,7 +705,7 @@ nvc0_fifo_init(struct nouveau_object *object)
nv_wr32(priv, 0x002a00, 0xffffffff); /* clears PFIFO.INTR bit 30 */ nv_wr32(priv, 0x002a00, 0xffffffff); /* clears PFIFO.INTR bit 30 */
nv_wr32(priv, 0x002100, 0xffffffff); nv_wr32(priv, 0x002100, 0xffffffff);
nv_wr32(priv, 0x002140, 0xbfffffff); nv_wr32(priv, 0x002140, 0x3fffffff);
return 0; return 0;
} }
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include <core/namedb.h> #include <core/namedb.h>
#include <core/gpuobj.h> #include <core/gpuobj.h>
#include <core/engctx.h> #include <core/engctx.h>
#include <core/event.h>
#include <core/class.h> #include <core/class.h>
#include <core/math.h> #include <core/math.h>
#include <core/enum.h> #include <core/enum.h>
...@@ -554,6 +555,12 @@ nve0_fifo_intr(struct nouveau_subdev *subdev) ...@@ -554,6 +555,12 @@ nve0_fifo_intr(struct nouveau_subdev *subdev)
stat &= ~0x40000000; stat &= ~0x40000000;
} }
if (stat & 0x80000000) {
nouveau_event_trigger(priv->base.uevent, 0);
nv_wr32(priv, 0x002100, 0x80000000);
stat &= ~0x80000000;
}
if (stat) { if (stat) {
nv_fatal(priv, "unhandled status 0x%08x\n", stat); nv_fatal(priv, "unhandled status 0x%08x\n", stat);
nv_wr32(priv, 0x002100, stat); nv_wr32(priv, 0x002100, stat);
...@@ -561,6 +568,20 @@ nve0_fifo_intr(struct nouveau_subdev *subdev) ...@@ -561,6 +568,20 @@ nve0_fifo_intr(struct nouveau_subdev *subdev)
} }
} }
static void
nve0_fifo_uevent_enable(struct nouveau_event *event, int index)
{
struct nve0_fifo_priv *priv = event->priv;
nv_mask(priv, 0x002140, 0x80000000, 0x80000000);
}
static void
nve0_fifo_uevent_disable(struct nouveau_event *event, int index)
{
struct nve0_fifo_priv *priv = event->priv;
nv_mask(priv, 0x002140, 0x80000000, 0x00000000);
}
static int static int
nve0_fifo_ctor(struct nouveau_object *parent, struct nouveau_object *engine, nve0_fifo_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
struct nouveau_oclass *oclass, void *data, u32 size, struct nouveau_oclass *oclass, void *data, u32 size,
...@@ -584,6 +605,10 @@ nve0_fifo_ctor(struct nouveau_object *parent, struct nouveau_object *engine, ...@@ -584,6 +605,10 @@ nve0_fifo_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
if (ret) if (ret)
return ret; return ret;
priv->base.uevent->enable = nve0_fifo_uevent_enable;
priv->base.uevent->disable = nve0_fifo_uevent_disable;
priv->base.uevent->priv = priv;
nv_subdev(priv)->unit = 0x00000100; nv_subdev(priv)->unit = 0x00000100;
nv_subdev(priv)->intr = nve0_fifo_intr; nv_subdev(priv)->intr = nve0_fifo_intr;
nv_engine(priv)->cclass = &nve0_fifo_cclass; nv_engine(priv)->cclass = &nve0_fifo_cclass;
...@@ -634,7 +659,7 @@ nve0_fifo_init(struct nouveau_object *object) ...@@ -634,7 +659,7 @@ nve0_fifo_init(struct nouveau_object *object)
nv_wr32(priv, 0x002a00, 0xffffffff); nv_wr32(priv, 0x002a00, 0xffffffff);
nv_wr32(priv, 0x002100, 0xffffffff); nv_wr32(priv, 0x002100, 0xffffffff);
nv_wr32(priv, 0x002140, 0xbfffffff); nv_wr32(priv, 0x002140, 0x3fffffff);
return 0; return 0;
} }
......
...@@ -65,6 +65,8 @@ struct nouveau_fifo_base { ...@@ -65,6 +65,8 @@ struct nouveau_fifo_base {
struct nouveau_fifo { struct nouveau_fifo {
struct nouveau_engine base; struct nouveau_engine base;
struct nouveau_event *uevent;
struct nouveau_object **channel; struct nouveau_object **channel;
spinlock_t lock; spinlock_t lock;
u16 min; u16 min;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment