diff options
author | Francisco Jerez <currojerez@riseup.net> | 2010-10-17 20:58:04 -0400 |
---|---|---|
committer | Ben Skeggs <bskeggs@redhat.com> | 2010-12-03 00:06:38 -0500 |
commit | feeb0aecfb73b5b7699c0a85ba1650e6f9c50be2 (patch) | |
tree | 9b0d496bf886399aa40c416665c61ef43db230b1 /drivers/gpu/drm | |
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')
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_channel.c | 36 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_drv.h | 3 |
2 files changed, 26 insertions, 13 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_channel.c b/drivers/gpu/drm/nouveau/nouveau_channel.c index c46a6f641964..38929fd3f4e3 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, | |||
238 | } | 238 | } |
239 | 239 | ||
240 | struct nouveau_channel * | 240 | struct nouveau_channel * |
241 | nouveau_channel_get_unlocked(struct nouveau_channel *ref) | ||
242 | { | ||
243 | if (likely(ref && atomic_inc_not_zero(&ref->refcount))) | ||
244 | return ref; | ||
245 | |||
246 | return NULL; | ||
247 | } | ||
248 | |||
249 | struct nouveau_channel * | ||
241 | nouveau_channel_get(struct drm_device *dev, struct drm_file *file_priv, int id) | 250 | nouveau_channel_get(struct drm_device *dev, struct drm_file *file_priv, int id) |
242 | { | 251 | { |
243 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 252 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
244 | struct nouveau_channel *chan = ERR_PTR(-ENODEV); | 253 | struct nouveau_channel *chan; |
245 | unsigned long flags; | 254 | unsigned long flags; |
246 | 255 | ||
247 | spin_lock_irqsave(&dev_priv->channels.lock, flags); | 256 | spin_lock_irqsave(&dev_priv->channels.lock, flags); |
248 | chan = dev_priv->channels.ptr[id]; | 257 | chan = nouveau_channel_get_unlocked(dev_priv->channels.ptr[id]); |
258 | spin_unlock_irqrestore(&dev_priv->channels.lock, flags); | ||
249 | 259 | ||
250 | if (unlikely(!chan || (file_priv && chan->file_priv != file_priv))) { | 260 | if (unlikely(!chan)) |
251 | spin_unlock_irqrestore(&dev_priv->channels.lock, flags); | ||
252 | return ERR_PTR(-EINVAL); | 261 | return ERR_PTR(-EINVAL); |
253 | } | ||
254 | 262 | ||
255 | if (unlikely(!atomic_inc_not_zero(&chan->refcount))) { | 263 | if (unlikely(file_priv && chan->file_priv != file_priv)) { |
256 | spin_unlock_irqrestore(&dev_priv->channels.lock, flags); | 264 | nouveau_channel_put_unlocked(&chan); |
257 | return ERR_PTR(-EINVAL); | 265 | return ERR_PTR(-EINVAL); |
258 | } | 266 | } |
259 | 267 | ||
260 | spin_unlock_irqrestore(&dev_priv->channels.lock, flags); | ||
261 | |||
262 | mutex_lock(&chan->mutex); | 268 | mutex_lock(&chan->mutex); |
263 | return chan; | 269 | return chan; |
264 | } | 270 | } |
265 | 271 | ||
266 | void | 272 | void |
267 | nouveau_channel_put(struct nouveau_channel **pchan) | 273 | nouveau_channel_put_unlocked(struct nouveau_channel **pchan) |
268 | { | 274 | { |
269 | struct nouveau_channel *chan = *pchan; | 275 | struct nouveau_channel *chan = *pchan; |
270 | struct drm_device *dev = chan->dev; | 276 | struct drm_device *dev = chan->dev; |
@@ -274,9 +280,6 @@ nouveau_channel_put(struct nouveau_channel **pchan) | |||
274 | unsigned long flags; | 280 | unsigned long flags; |
275 | int ret; | 281 | int ret; |
276 | 282 | ||
277 | /* unlock the channel */ | ||
278 | mutex_unlock(&chan->mutex); | ||
279 | |||
280 | /* decrement the refcount, and we're done if there's still refs */ | 283 | /* decrement the refcount, and we're done if there's still refs */ |
281 | if (likely(!atomic_dec_and_test(&chan->refcount))) { | 284 | if (likely(!atomic_dec_and_test(&chan->refcount))) { |
282 | *pchan = NULL; | 285 | *pchan = NULL; |
@@ -348,6 +351,13 @@ nouveau_channel_put(struct nouveau_channel **pchan) | |||
348 | kfree(chan); | 351 | kfree(chan); |
349 | } | 352 | } |
350 | 353 | ||
354 | void | ||
355 | nouveau_channel_put(struct nouveau_channel **pchan) | ||
356 | { | ||
357 | mutex_unlock(&(*pchan)->mutex); | ||
358 | nouveau_channel_put_unlocked(pchan); | ||
359 | } | ||
360 | |||
351 | /* cleans up all the fifos from file_priv */ | 361 | /* cleans up all the fifos from file_priv */ |
352 | void | 362 | void |
353 | nouveau_channel_cleanup(struct drm_device *dev, struct drm_file *file_priv) | 363 | nouveau_channel_cleanup(struct drm_device *dev, struct drm_file *file_priv) |
diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h index 198dabebafb2..e6708be58bcf 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.h +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h | |||
@@ -803,7 +803,10 @@ extern int nouveau_channel_alloc(struct drm_device *dev, | |||
803 | struct drm_file *file_priv, | 803 | struct drm_file *file_priv, |
804 | uint32_t fb_ctxdma, uint32_t tt_ctxdma); | 804 | uint32_t fb_ctxdma, uint32_t tt_ctxdma); |
805 | extern struct nouveau_channel * | 805 | extern struct nouveau_channel * |
806 | nouveau_channel_get_unlocked(struct nouveau_channel *); | ||
807 | extern struct nouveau_channel * | ||
806 | nouveau_channel_get(struct drm_device *, struct drm_file *, int id); | 808 | nouveau_channel_get(struct drm_device *, struct drm_file *, int id); |
809 | extern void nouveau_channel_put_unlocked(struct nouveau_channel **); | ||
807 | extern void nouveau_channel_put(struct nouveau_channel **); | 810 | extern void nouveau_channel_put(struct nouveau_channel **); |
808 | 811 | ||
809 | /* nouveau_object.c */ | 812 | /* nouveau_object.c */ |