summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/nouveau/nouveau_irq.c
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2010-10-06 10:16:59 +0400
committerBen Skeggs <bskeggs@redhat.com>2010-12-03 08:05:18 +0300
commitcff5c1332486ced8ff4180e957e04983cb72a39e (patch)
treeec1f6687156277632aef96693c1b8eca0c022b7c /drivers/gpu/drm/nouveau/nouveau_irq.c
parent6a6b73f254123851f7f73ab5e57344a569d6a0ab (diff)
downloadlinux-cff5c1332486ced8ff4180e957e04983cb72a39e.tar.xz
drm/nouveau: add more fine-grained locking to channel list + structures
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/nouveau/nouveau_irq.c')
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_irq.c42
1 files changed, 28 insertions, 14 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_irq.c b/drivers/gpu/drm/nouveau/nouveau_irq.c
index a4fa9e14d66d..c5e37bc17192 100644
--- a/drivers/gpu/drm/nouveau/nouveau_irq.c
+++ b/drivers/gpu/drm/nouveau/nouveau_irq.c
@@ -113,15 +113,17 @@ nouveau_fifo_swmthd(struct drm_device *dev, u32 chid, u32 addr, u32 data)
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_channel *chan = NULL;
struct nouveau_gpuobj *obj;
+ unsigned long flags;
const int subc = (addr >> 13) & 0x7;
const int mthd = addr & 0x1ffc;
bool handled = false;
u32 engine;
+ spin_lock_irqsave(&dev_priv->channels.lock, flags);
if (likely(chid >= 0 && chid < dev_priv->engine.fifo.channels))
- chan = dev_priv->fifos[chid];
+ chan = dev_priv->channels.ptr[chid];
if (unlikely(!chan))
- return false;
+ goto out;
switch (mthd) {
case 0x0000: /* bind object to subchannel */
@@ -146,6 +148,8 @@ nouveau_fifo_swmthd(struct drm_device *dev, u32 chid, u32 addr, u32 data)
break;
}
+out:
+ spin_unlock_irqrestore(&dev_priv->channels.lock, flags);
return handled;
}
@@ -398,6 +402,8 @@ static int
nouveau_graph_chid_from_grctx(struct drm_device *dev)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
+ struct nouveau_channel *chan;
+ unsigned long flags;
uint32_t inst;
int i;
@@ -407,27 +413,29 @@ nouveau_graph_chid_from_grctx(struct drm_device *dev)
if (dev_priv->card_type < NV_50) {
inst = (nv_rd32(dev, 0x40032c) & 0xfffff) << 4;
+ spin_lock_irqsave(&dev_priv->channels.lock, flags);
for (i = 0; i < dev_priv->engine.fifo.channels; i++) {
- struct nouveau_channel *chan = dev_priv->fifos[i];
-
+ chan = dev_priv->channels.ptr[i];
if (!chan || !chan->ramin_grctx)
continue;
if (inst == chan->ramin_grctx->pinst)
break;
}
+ spin_unlock_irqrestore(&dev_priv->channels.lock, flags);
} else {
inst = (nv_rd32(dev, 0x40032c) & 0xfffff) << 12;
+ spin_lock_irqsave(&dev_priv->channels.lock, flags);
for (i = 0; i < dev_priv->engine.fifo.channels; i++) {
- struct nouveau_channel *chan = dev_priv->fifos[i];
-
+ chan = dev_priv->channels.ptr[i];
if (!chan || !chan->ramin)
continue;
if (inst == chan->ramin->vinst)
break;
}
+ spin_unlock_irqrestore(&dev_priv->channels.lock, flags);
}
@@ -449,7 +457,8 @@ nouveau_graph_trapped_channel(struct drm_device *dev, int *channel_ret)
else
channel = nouveau_graph_chid_from_grctx(dev);
- if (channel >= engine->fifo.channels || !dev_priv->fifos[channel]) {
+ if (channel >= engine->fifo.channels ||
+ !dev_priv->channels.ptr[channel]) {
NV_ERROR(dev, "AIII, invalid/inactive channel id %d\n", channel);
return -EINVAL;
}
@@ -532,14 +541,19 @@ nouveau_pgraph_intr_swmthd(struct drm_device *dev,
struct nouveau_pgraph_trap *trap)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
+ unsigned long flags;
+ int ret = -EINVAL;
+
+ spin_lock_irqsave(&dev_priv->channels.lock, flags);
+ if (trap->channel > 0 &&
+ trap->channel < dev_priv->engine.fifo.channels &&
+ dev_priv->channels.ptr[trap->channel]) {
+ ret = nouveau_call_method(dev_priv->channels.ptr[trap->channel],
+ trap->class, trap->mthd, trap->data);
+ }
+ spin_unlock_irqrestore(&dev_priv->channels.lock, flags);
- if (trap->channel < 0 ||
- trap->channel >= dev_priv->engine.fifo.channels ||
- !dev_priv->fifos[trap->channel])
- return -ENODEV;
-
- return nouveau_call_method(dev_priv->fifos[trap->channel],
- trap->class, trap->mthd, trap->data);
+ return ret;
}
static inline void