diff options
author | Francisco Jerez <currojerez@riseup.net> | 2010-10-18 02:58:04 +0200 |
---|---|---|
committer | Ben Skeggs <bskeggs@redhat.com> | 2010-12-03 15:06:38 +1000 |
commit | feeb0aecfb73b5b7699c0a85ba1650e6f9c50be2 (patch) | |
tree | 9b0d496bf886399aa40c416665c61ef43db230b1 /drivers/gpu/drm/nouveau/nouveau_channel.c | |
parent | f175b745b50c5c5356e8b3b409b7f38aa44de6bb (diff) |
drm/nouveau: Add unlocked variants of nouveau_channel_get/put.
Signed-off-by: Francisco Jerez <currojerez@riseup.net>
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/nouveau/nouveau_channel.c')
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_channel.c | 36 |
1 files changed, 23 insertions, 13 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_channel.c b/drivers/gpu/drm/nouveau/nouveau_channel.c index c46a6f64196..38929fd3f4e 100644 --- a/drivers/gpu/drm/nouveau/nouveau_channel.c +++ b/drivers/gpu/drm/nouveau/nouveau_channel.c @@ -238,33 +238,39 @@ nouveau_channel_alloc(struct drm_device *dev, struct nouveau_channel **chan_ret, } struct nouveau_channel * +nouveau_channel_get_unlocked(struct nouveau_channel *ref) +{ + if (likely(ref && atomic_inc_not_zero(&ref->refcount))) + return ref; + + return NULL; +} + +struct nouveau_channel * nouveau_channel_get(struct drm_device *dev, struct drm_file *file_priv, int id) { struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_channel *chan = ERR_PTR(-ENODEV); + struct nouveau_channel *chan; unsigned long flags; spin_lock_irqsave(&dev_priv->channels.lock, flags); - chan = dev_priv->channels.ptr[id]; + chan = nouveau_channel_get_unlocked(dev_priv->channels.ptr[id]); + spin_unlock_irqrestore(&dev_priv->channels.lock, flags); - if (unlikely(!chan || (file_priv && chan->file_priv != file_priv))) { - spin_unlock_irqrestore(&dev_priv->channels.lock, flags); + if (unlikely(!chan)) return ERR_PTR(-EINVAL); - } - if (unlikely(!atomic_inc_not_zero(&chan->refcount))) { - spin_unlock_irqrestore(&dev_priv->channels.lock, flags); + if (unlikely(file_priv && chan->file_priv != file_priv)) { + nouveau_channel_put_unlocked(&chan); return ERR_PTR(-EINVAL); } - spin_unlock_irqrestore(&dev_priv->channels.lock, flags); - mutex_lock(&chan->mutex); return chan; } void -nouveau_channel_put(struct nouveau_channel **pchan) +nouveau_channel_put_unlocked(struct nouveau_channel **pchan) { struct nouveau_channel *chan = *pchan; struct drm_device *dev = chan->dev; @@ -274,9 +280,6 @@ nouveau_channel_put(struct nouveau_channel **pchan) unsigned long flags; int ret; - /* unlock the channel */ - mutex_unlock(&chan->mutex); - /* decrement the refcount, and we're done if there's still refs */ if (likely(!atomic_dec_and_test(&chan->refcount))) { *pchan = NULL; @@ -348,6 +351,13 @@ nouveau_channel_put(struct nouveau_channel **pchan) kfree(chan); } +void +nouveau_channel_put(struct nouveau_channel **pchan) +{ + mutex_unlock(&(*pchan)->mutex); + nouveau_channel_put_unlocked(pchan); +} + /* cleans up all the fifos from file_priv */ void nouveau_channel_cleanup(struct drm_device *dev, struct drm_file *file_priv) |