summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2010-09-23 11:03:01 +1000
committerBen Skeggs <bskeggs@redhat.com>2010-12-03 14:18:39 +1000
commit7c74cbd01b2698583fb74ebdfcd7ef4c768e6346 (patch)
treef507a89cdc646bf03c551c37e56505a0a9c15978
parentf7eb0c55416aba7478932cedbaccc2bdacd8a95d (diff)
drm/nouveau: tidy fifo swmthd handler a little
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_irq.c56
1 files changed, 31 insertions, 25 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_irq.c b/drivers/gpu/drm/nouveau/nouveau_irq.c
index 7bfd9e6c9d67..a4fa9e14d66d 100644
--- a/drivers/gpu/drm/nouveau/nouveau_irq.c
+++ b/drivers/gpu/drm/nouveau/nouveau_irq.c
@@ -108,36 +108,45 @@ nouveau_call_method(struct nouveau_channel *chan, int class, int mthd, int data)
}
static bool
-nouveau_fifo_swmthd(struct nouveau_channel *chan, uint32_t addr, uint32_t data)
+nouveau_fifo_swmthd(struct drm_device *dev, u32 chid, u32 addr, u32 data)
{
- struct drm_device *dev = chan->dev;
+ struct drm_nouveau_private *dev_priv = dev->dev_private;
+ struct nouveau_channel *chan = NULL;
+ struct nouveau_gpuobj *obj;
const int subc = (addr >> 13) & 0x7;
const int mthd = addr & 0x1ffc;
+ bool handled = false;
+ u32 engine;
- if (mthd == 0x0000) {
- struct nouveau_gpuobj *gpuobj;
-
- gpuobj = nouveau_ramht_find(chan, data);
- if (!gpuobj)
- return false;
+ if (likely(chid >= 0 && chid < dev_priv->engine.fifo.channels))
+ chan = dev_priv->fifos[chid];
+ if (unlikely(!chan))
+ return false;
- if (gpuobj->engine != NVOBJ_ENGINE_SW)
- return false;
+ switch (mthd) {
+ case 0x0000: /* bind object to subchannel */
+ obj = nouveau_ramht_find(chan, data);
+ if (unlikely(!obj || obj->engine != NVOBJ_ENGINE_SW))
+ break;
- chan->sw_subchannel[subc] = gpuobj->class;
- nv_wr32(dev, NV04_PFIFO_CACHE1_ENGINE, nv_rd32(dev,
- NV04_PFIFO_CACHE1_ENGINE) & ~(0xf << subc * 4));
- return true;
- }
+ chan->sw_subchannel[subc] = obj->class;
+ engine = 0x0000000f << (subc * 4);
- /* hw object */
- if (nv_rd32(dev, NV04_PFIFO_CACHE1_ENGINE) & (1 << (subc*4)))
- return false;
+ nv_mask(dev, NV04_PFIFO_CACHE1_ENGINE, engine, 0x00000000);
+ handled = true;
+ break;
+ default:
+ engine = nv_rd32(dev, NV04_PFIFO_CACHE1_ENGINE);
+ if (unlikely(((engine >> (subc * 4)) & 0xf) != 0))
+ break;
- if (nouveau_call_method(chan, chan->sw_subchannel[subc], mthd, data))
- return false;
+ if (!nouveau_call_method(chan, chan->sw_subchannel[subc],
+ mthd, data))
+ handled = true;
+ break;
+ }
- return true;
+ return handled;
}
static void
@@ -150,14 +159,11 @@ nouveau_fifo_irq_handler(struct drm_device *dev)
reassign = nv_rd32(dev, NV03_PFIFO_CACHES) & 1;
while ((status = nv_rd32(dev, NV03_PFIFO_INTR_0)) && (cnt++ < 100)) {
- struct nouveau_channel *chan = NULL;
uint32_t chid, get;
nv_wr32(dev, NV03_PFIFO_CACHES, 0);
chid = engine->fifo.channel_id(dev);
- if (chid >= 0 && chid < engine->fifo.channels)
- chan = dev_priv->fifos[chid];
get = nv_rd32(dev, NV03_PFIFO_CACHE1_GET);
if (status & NV_PFIFO_INTR_CACHE_ERROR) {
@@ -184,7 +190,7 @@ nouveau_fifo_irq_handler(struct drm_device *dev)
NV40_PFIFO_CACHE1_DATA(ptr));
}
- if (!chan || !nouveau_fifo_swmthd(chan, mthd, data)) {
+ if (!nouveau_fifo_swmthd(dev, chid, mthd, data)) {
NV_INFO(dev, "PFIFO_CACHE_ERROR - Ch %d/%d "
"Mthd 0x%04x Data 0x%08x\n",
chid, (mthd >> 13) & 7, mthd & 0x1ffc,