summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/nouveau/core/engine/fifo
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2014-02-22 00:31:29 +1000
committerBen Skeggs <bskeggs@redhat.com>2014-03-26 14:00:43 +1000
commit083c214241b9de43dbbcb6ef8e306abeb3feba95 (patch)
tree215dfd65563d9ff213f1f942dc77a935815aae5a /drivers/gpu/drm/nouveau/core/engine/fifo
parenta07d0e768c6610c8e358c27c9e16f10672a93a05 (diff)
downloadop-kernel-dev-083c214241b9de43dbbcb6ef8e306abeb3feba95.zip
op-kernel-dev-083c214241b9de43dbbcb6ef8e306abeb3feba95.tar.gz
drm/nvc0/fifo: ack pb intr individually after handling each unit
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/nouveau/core/engine/fifo')
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c82
1 files changed, 40 insertions, 42 deletions
diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c
index 5aa03f9..9939044 100644
--- a/drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c
+++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c
@@ -345,6 +345,32 @@ nvc0_fifo_cclass = {
* PFIFO engine
******************************************************************************/
+static int
+nvc0_fifo_swmthd(struct nvc0_fifo_priv *priv, u32 chid, u32 mthd, u32 data)
+{
+ struct nvc0_fifo_chan *chan = NULL;
+ struct nouveau_handle *bind;
+ unsigned long flags;
+ int ret = -EINVAL;
+
+ spin_lock_irqsave(&priv->base.lock, flags);
+ if (likely(chid >= priv->base.min && chid <= priv->base.max))
+ chan = (void *)priv->base.channel[chid];
+ if (unlikely(!chan))
+ goto out;
+
+ bind = nouveau_namedb_get_class(nv_namedb(chan), 0x906e);
+ if (likely(bind)) {
+ if (!mthd || !nv_call(bind->object, mthd, data))
+ ret = 0;
+ nouveau_namedb_put(bind);
+ }
+
+out:
+ spin_unlock_irqrestore(&priv->base.lock, flags);
+ return ret;
+}
+
static const struct nouveau_enum nvc0_fifo_fault_unit[] = {
{ 0x00, "PGRAPH", NULL, NVDEV_ENGINE_GR },
{ 0x03, "PEEPHOLE" },
@@ -400,13 +426,6 @@ static const struct nouveau_enum nvc0_fifo_fault_gpcclient[] = {
{}
};
-static const struct nouveau_bitfield nvc0_fifo_pbdma_intr[] = {
-/* { 0x00008000, "" } seen with null ib push */
- { 0x00200000, "ILLEGAL_MTHD" },
- { 0x00800000, "EMPTY_SUBC" },
- {}
-};
-
static void
nvc0_fifo_isr_vm_fault(struct nvc0_fifo_priv *priv, int unit)
{
@@ -458,34 +477,16 @@ nvc0_fifo_isr_vm_fault(struct nvc0_fifo_priv *priv, int unit)
nouveau_engctx_put(engctx);
}
-static int
-nvc0_fifo_swmthd(struct nvc0_fifo_priv *priv, u32 chid, u32 mthd, u32 data)
-{
- struct nvc0_fifo_chan *chan = NULL;
- struct nouveau_handle *bind;
- unsigned long flags;
- int ret = -EINVAL;
-
- spin_lock_irqsave(&priv->base.lock, flags);
- if (likely(chid >= priv->base.min && chid <= priv->base.max))
- chan = (void *)priv->base.channel[chid];
- if (unlikely(!chan))
- goto out;
-
- bind = nouveau_namedb_get_class(nv_namedb(chan), 0x906e);
- if (likely(bind)) {
- if (!mthd || !nv_call(bind->object, mthd, data))
- ret = 0;
- nouveau_namedb_put(bind);
- }
-
-out:
- spin_unlock_irqrestore(&priv->base.lock, flags);
- return ret;
-}
+static const struct nouveau_bitfield
+nvc0_fifo_pbdma_intr[] = {
+/* { 0x00008000, "" } seen with null ib push */
+ { 0x00200000, "ILLEGAL_MTHD" },
+ { 0x00800000, "EMPTY_SUBC" },
+ {}
+};
static void
-nvc0_fifo_isr_pbdma_intr(struct nvc0_fifo_priv *priv, int unit)
+nvc0_fifo_intr_pbdma(struct nvc0_fifo_priv *priv, int unit)
{
u32 stat = nv_rd32(priv, 0x040108 + (unit * 0x2000));
u32 addr = nv_rd32(priv, 0x0400c0 + (unit * 0x2000));
@@ -615,16 +616,13 @@ nvc0_fifo_intr(struct nouveau_subdev *subdev)
}
if (stat & 0x20000000) {
- u32 units = nv_rd32(priv, 0x0025a0);
- u32 u = units;
-
- while (u) {
- int i = __ffs(u);
- nvc0_fifo_isr_pbdma_intr(priv, i);
- u &= ~(1 << i);
+ u32 mask = nv_rd32(priv, 0x0025a0);
+ while (mask) {
+ u32 unit = __ffs(mask);
+ nvc0_fifo_intr_pbdma(priv, unit);
+ nv_wr32(priv, 0x0025a0, (1 << unit));
+ mask &= ~(1 << unit);
}
-
- nv_wr32(priv, 0x0025a0, units);
stat &= ~0x20000000;
}
OpenPOWER on IntegriCloud