Merge branch 'master' of git+ssh://git.freedesktop.org/git/mesa/drm into modesetting-101
[platform/upstream/libdrm.git] / linux-core / drm_fence.c
1 /**************************************************************************
2  *
3  * Copyright (c) 2006-2007 Tungsten Graphics, Inc., Cedar Park, TX., USA
4  * All Rights Reserved.
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a
7  * copy of this software and associated documentation files (the
8  * "Software"), to deal in the Software without restriction, including
9  * without limitation the rights to use, copy, modify, merge, publish,
10  * distribute, sub license, and/or sell copies of the Software, and to
11  * permit persons to whom the Software is furnished to do so, subject to
12  * the following conditions:
13  *
14  * The above copyright notice and this permission notice (including the
15  * next paragraph) shall be included in all copies or substantial portions
16  * of the Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
21  * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
22  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
23  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
24  * USE OR OTHER DEALINGS IN THE SOFTWARE.
25  *
26  **************************************************************************/
27 /*
28  * Authors: Thomas Hellström <thomas-at-tungstengraphics-dot-com>
29  */
30
31 #include "drmP.h"
32
33
34 /*
35  * Convenience function to be called by fence::wait methods that
36  * need polling.
37  */
38
39 int drm_fence_wait_polling(struct drm_fence_object *fence, int lazy,
40                            int interruptible, uint32_t mask, 
41                            unsigned long end_jiffies)
42 {
43         struct drm_device *dev = fence->dev;
44         struct drm_fence_manager *fm = &dev->fm;
45         struct drm_fence_class_manager *fc = &fm->fence_class[fence->fence_class];
46         uint32_t count = 0;
47         int ret;
48
49         DECLARE_WAITQUEUE(entry, current);
50         add_wait_queue(&fc->fence_queue, &entry);
51
52         ret = 0;
53         
54         for (;;) {
55                 __set_current_state((interruptible) ? 
56                                     TASK_INTERRUPTIBLE :
57                                     TASK_UNINTERRUPTIBLE);
58                 if (drm_fence_object_signaled(fence, mask))
59                         break;
60                 if (time_after_eq(jiffies, end_jiffies)) {
61                         ret = -EBUSY;
62                         break;
63                 }
64                 if (lazy)
65                         schedule_timeout(1);
66                 else if ((++count & 0x0F) == 0){
67                         __set_current_state(TASK_RUNNING);
68                         schedule();
69                         __set_current_state((interruptible) ? 
70                                             TASK_INTERRUPTIBLE :
71                                             TASK_UNINTERRUPTIBLE);
72                 }                       
73                 if (interruptible && signal_pending(current)) {
74                         ret = -EAGAIN;
75                         break;
76                 }
77         }
78         __set_current_state(TASK_RUNNING);
79         remove_wait_queue(&fc->fence_queue, &entry);
80         return ret;
81 }
82 EXPORT_SYMBOL(drm_fence_wait_polling);
83
84 /*
85  * Typically called by the IRQ handler.
86  */
87
88 void drm_fence_handler(struct drm_device *dev, uint32_t fence_class,
89                        uint32_t sequence, uint32_t type, uint32_t error)
90 {
91         int wake = 0;
92         uint32_t diff;
93         uint32_t relevant_type;
94         uint32_t new_type;
95         struct drm_fence_manager *fm = &dev->fm;
96         struct drm_fence_class_manager *fc = &fm->fence_class[fence_class];
97         struct drm_fence_driver *driver = dev->driver->fence_driver;
98         struct list_head *head;
99         struct drm_fence_object *fence, *next;
100         int found = 0;
101
102         if (list_empty(&fc->ring))
103                 return;
104
105         list_for_each_entry(fence, &fc->ring, ring) {
106                 diff = (sequence - fence->sequence) & driver->sequence_mask;
107                 if (diff > driver->wrap_diff) {
108                         found = 1;
109                         break;
110                 }
111         }
112
113         fc->waiting_types &= ~type;
114         head = (found) ? &fence->ring : &fc->ring;
115
116         list_for_each_entry_safe_reverse(fence, next, head, ring) {
117                 if (&fence->ring == &fc->ring)
118                         break;
119
120                 if (error) {
121                         fence->error = error;
122                         fence->signaled_types = fence->type;
123                         list_del_init(&fence->ring);
124                         wake = 1;
125                         break;
126                 }
127
128                 if (type & DRM_FENCE_TYPE_EXE)
129                         type |= fence->native_types;
130
131                 relevant_type = type & fence->type;
132                 new_type = (fence->signaled_types | relevant_type) ^
133                         fence->signaled_types;
134
135                 if (new_type) {
136                         fence->signaled_types |= new_type;
137                         DRM_DEBUG("Fence 0x%08lx signaled 0x%08x\n",
138                                   fence->base.hash.key, fence->signaled_types);
139
140                         if (driver->needed_flush)
141                                 fc->pending_flush |= driver->needed_flush(fence);
142
143                         if (new_type & fence->waiting_types)
144                                 wake = 1;
145                 }
146
147                 fc->waiting_types |= fence->waiting_types & ~fence->signaled_types;
148
149                 if (!(fence->type & ~fence->signaled_types)) {
150                         DRM_DEBUG("Fence completely signaled 0x%08lx\n",
151                                   fence->base.hash.key);
152                         list_del_init(&fence->ring);
153                 }
154         }
155
156         /*
157          * Reinstate lost waiting types.
158          */
159
160         if ((fc->waiting_types & type) != type) {
161                 head = head->prev;
162                 list_for_each_entry(fence, head, ring) {
163                         if (&fence->ring == &fc->ring)
164                                 break;
165                         diff = (fc->highest_waiting_sequence - fence->sequence) &
166                                 driver->sequence_mask;
167                         if (diff > driver->wrap_diff)
168                                 break;
169                         
170                         fc->waiting_types |= fence->waiting_types & ~fence->signaled_types;
171                 }
172         }
173
174         if (wake) 
175                 wake_up_all(&fc->fence_queue);
176 }
177 EXPORT_SYMBOL(drm_fence_handler);
178
179 static void drm_fence_unring(struct drm_device *dev, struct list_head *ring)
180 {
181         struct drm_fence_manager *fm = &dev->fm;
182         unsigned long flags;
183
184         write_lock_irqsave(&fm->lock, flags);
185         list_del_init(ring);
186         write_unlock_irqrestore(&fm->lock, flags);
187 }
188
189 void drm_fence_usage_deref_locked(struct drm_fence_object **fence)
190 {
191         struct drm_fence_object *tmp_fence = *fence;
192         struct drm_device *dev = tmp_fence->dev;
193         struct drm_fence_manager *fm = &dev->fm;
194
195         DRM_ASSERT_LOCKED(&dev->struct_mutex);
196         *fence = NULL;
197         if (atomic_dec_and_test(&tmp_fence->usage)) {
198                 drm_fence_unring(dev, &tmp_fence->ring);
199                 DRM_DEBUG("Destroyed a fence object 0x%08lx\n",
200                           tmp_fence->base.hash.key);
201                 atomic_dec(&fm->count);
202                 BUG_ON(!list_empty(&tmp_fence->base.list));
203                 drm_ctl_free(tmp_fence, sizeof(*tmp_fence), DRM_MEM_FENCE);
204         }
205 }
206 EXPORT_SYMBOL(drm_fence_usage_deref_locked);
207
208 void drm_fence_usage_deref_unlocked(struct drm_fence_object **fence)
209 {
210         struct drm_fence_object *tmp_fence = *fence;
211         struct drm_device *dev = tmp_fence->dev;
212         struct drm_fence_manager *fm = &dev->fm;
213
214         *fence = NULL;
215         if (atomic_dec_and_test(&tmp_fence->usage)) {
216                 mutex_lock(&dev->struct_mutex);
217                 if (atomic_read(&tmp_fence->usage) == 0) {
218                         drm_fence_unring(dev, &tmp_fence->ring);
219                         atomic_dec(&fm->count);
220                         BUG_ON(!list_empty(&tmp_fence->base.list));
221                         drm_ctl_free(tmp_fence, sizeof(*tmp_fence), DRM_MEM_FENCE);
222                 }
223                 mutex_unlock(&dev->struct_mutex);
224         }
225 }
226 EXPORT_SYMBOL(drm_fence_usage_deref_unlocked);
227
228 struct drm_fence_object
229 *drm_fence_reference_locked(struct drm_fence_object *src)
230 {
231         DRM_ASSERT_LOCKED(&src->dev->struct_mutex);
232
233         atomic_inc(&src->usage);
234         return src;
235 }
236
237 void drm_fence_reference_unlocked(struct drm_fence_object **dst,
238                                   struct drm_fence_object *src)
239 {
240         mutex_lock(&src->dev->struct_mutex);
241         *dst = src;
242         atomic_inc(&src->usage);
243         mutex_unlock(&src->dev->struct_mutex);
244 }
245 EXPORT_SYMBOL(drm_fence_reference_unlocked);
246
247 static void drm_fence_object_destroy(struct drm_file *priv,
248                                      struct drm_user_object *base)
249 {
250         struct drm_fence_object *fence =
251             drm_user_object_entry(base, struct drm_fence_object, base);
252
253         drm_fence_usage_deref_locked(&fence);
254 }
255
256 int drm_fence_object_signaled(struct drm_fence_object *fence, uint32_t mask)
257 {
258         unsigned long flags;
259         int signaled;
260         struct drm_device *dev = fence->dev;
261         struct drm_fence_manager *fm = &dev->fm;
262         struct drm_fence_driver *driver = dev->driver->fence_driver;
263         
264         mask &= fence->type;
265         read_lock_irqsave(&fm->lock, flags);
266         signaled = (mask & fence->signaled_types) == mask;
267         read_unlock_irqrestore(&fm->lock, flags);
268         if (!signaled && driver->poll) {
269                 write_lock_irqsave(&fm->lock, flags);
270                 driver->poll(dev, fence->fence_class, mask);
271                 signaled = (mask & fence->signaled_types) == mask;
272                 write_unlock_irqrestore(&fm->lock, flags);
273         }
274         return signaled;
275 }
276 EXPORT_SYMBOL(drm_fence_object_signaled);
277
278
279 int drm_fence_object_flush(struct drm_fence_object *fence,
280                            uint32_t type)
281 {
282         struct drm_device *dev = fence->dev;
283         struct drm_fence_manager *fm = &dev->fm;
284         struct drm_fence_class_manager *fc = &fm->fence_class[fence->fence_class];
285         struct drm_fence_driver *driver = dev->driver->fence_driver;
286         unsigned long irq_flags;
287         uint32_t saved_pending_flush;
288         uint32_t diff;
289         int call_flush;
290
291         if (type & ~fence->type) {
292                 DRM_ERROR("Flush trying to extend fence type, "
293                           "0x%x, 0x%x\n", type, fence->type);
294                 return -EINVAL;
295         }
296
297         write_lock_irqsave(&fm->lock, irq_flags);
298         fence->waiting_types |= type;
299         fc->waiting_types |= fence->waiting_types;
300         diff = (fence->sequence - fc->highest_waiting_sequence) & 
301                 driver->sequence_mask;
302
303         if (diff < driver->wrap_diff)
304                 fc->highest_waiting_sequence = fence->sequence;
305
306         /*
307          * fence->waiting_types has changed. Determine whether
308          * we need to initiate some kind of flush as a result of this.
309          */
310
311         saved_pending_flush = fc->pending_flush;
312         if (driver->needed_flush) 
313                 fc->pending_flush |= driver->needed_flush(fence);
314
315         if (driver->poll)
316                 driver->poll(dev, fence->fence_class, fence->waiting_types);
317
318         call_flush = fc->pending_flush;
319         write_unlock_irqrestore(&fm->lock, irq_flags);
320
321         if (call_flush && driver->flush)
322                 driver->flush(dev, fence->fence_class);
323
324         return 0;
325 }
326 EXPORT_SYMBOL(drm_fence_object_flush);
327
328 /*
329  * Make sure old fence objects are signaled before their fence sequences are
330  * wrapped around and reused.
331  */
332
333 void drm_fence_flush_old(struct drm_device *dev, uint32_t fence_class,
334                          uint32_t sequence)
335 {
336         struct drm_fence_manager *fm = &dev->fm;
337         struct drm_fence_class_manager *fc = &fm->fence_class[fence_class];
338         struct drm_fence_object *fence;
339         unsigned long irq_flags;
340         struct drm_fence_driver *driver = dev->driver->fence_driver;
341         int call_flush;
342
343         uint32_t diff;
344
345         write_lock_irqsave(&fm->lock, irq_flags);
346
347         list_for_each_entry_reverse(fence, &fc->ring, ring) {
348                 diff = (sequence - fence->sequence) & driver->sequence_mask;
349                 if (diff <= driver->flush_diff)
350                         break;
351         
352                 fence->waiting_types = fence->type;
353                 fc->waiting_types |= fence->type;
354
355                 if (driver->needed_flush)
356                         fc->pending_flush |= driver->needed_flush(fence);
357         }       
358         
359         if (driver->poll)
360                 driver->poll(dev, fence_class, fc->waiting_types);
361
362         call_flush = fc->pending_flush;
363         write_unlock_irqrestore(&fm->lock, irq_flags);
364
365         if (call_flush && driver->flush)
366                 driver->flush(dev, fence->fence_class);
367
368         /*
369          * FIXME: Shold we implement a wait here for really old fences?
370          */
371
372 }
373 EXPORT_SYMBOL(drm_fence_flush_old);
374
375 int drm_fence_object_wait(struct drm_fence_object *fence,
376                           int lazy, int ignore_signals, uint32_t mask)
377 {
378         struct drm_device *dev = fence->dev;
379         struct drm_fence_driver *driver = dev->driver->fence_driver;
380         struct drm_fence_manager *fm = &dev->fm;
381         struct drm_fence_class_manager *fc = &fm->fence_class[fence->fence_class];
382         int ret = 0;
383         unsigned long _end = 3 * DRM_HZ;
384
385         if (mask & ~fence->type) {
386                 DRM_ERROR("Wait trying to extend fence type"
387                           " 0x%08x 0x%08x\n", mask, fence->type);
388                 BUG();
389                 return -EINVAL;
390         }
391
392         if (driver->wait)
393                 return driver->wait(fence, lazy, !ignore_signals, mask);
394
395
396         drm_fence_object_flush(fence, mask);
397         if (driver->has_irq(dev, fence->fence_class, mask)) {
398                 if (!ignore_signals)
399                         ret = wait_event_interruptible_timeout
400                                 (fc->fence_queue, 
401                                  drm_fence_object_signaled(fence, mask), 
402                                  3 * DRM_HZ);
403                 else 
404                         ret = wait_event_timeout
405                                 (fc->fence_queue, 
406                                  drm_fence_object_signaled(fence, mask), 
407                                  3 * DRM_HZ);
408
409                 if (unlikely(ret == -ERESTARTSYS))
410                         return -EAGAIN;
411
412                 if (unlikely(ret == 0))
413                         return -EBUSY;
414
415                 return 0;
416         }
417
418         return drm_fence_wait_polling(fence, lazy, !ignore_signals, mask,
419                                       _end);
420 }
421 EXPORT_SYMBOL(drm_fence_object_wait);
422
423
424
425 int drm_fence_object_emit(struct drm_fence_object *fence, uint32_t fence_flags,
426                           uint32_t fence_class, uint32_t type)
427 {
428         struct drm_device *dev = fence->dev;
429         struct drm_fence_manager *fm = &dev->fm;
430         struct drm_fence_driver *driver = dev->driver->fence_driver;
431         struct drm_fence_class_manager *fc = &fm->fence_class[fence->fence_class];
432         unsigned long flags;
433         uint32_t sequence;
434         uint32_t native_types;
435         int ret;
436
437         drm_fence_unring(dev, &fence->ring);
438         ret = driver->emit(dev, fence_class, fence_flags, &sequence,
439                            &native_types);
440         if (ret)
441                 return ret;
442
443         write_lock_irqsave(&fm->lock, flags);
444         fence->fence_class = fence_class;
445         fence->type = type;
446         fence->waiting_types = 0;
447         fence->signaled_types = 0;
448         fence->sequence = sequence;
449         fence->native_types = native_types;
450         if (list_empty(&fc->ring))
451                 fc->highest_waiting_sequence = sequence - 1;
452         list_add_tail(&fence->ring, &fc->ring);
453         fc->latest_queued_sequence = sequence;
454         write_unlock_irqrestore(&fm->lock, flags);
455         return 0;
456 }
457 EXPORT_SYMBOL(drm_fence_object_emit);
458
459 static int drm_fence_object_init(struct drm_device *dev, uint32_t fence_class,
460                                  uint32_t type,
461                                  uint32_t fence_flags,
462                                  struct drm_fence_object *fence)
463 {
464         int ret = 0;
465         unsigned long flags;
466         struct drm_fence_manager *fm = &dev->fm;
467
468         mutex_lock(&dev->struct_mutex);
469         atomic_set(&fence->usage, 1);
470         mutex_unlock(&dev->struct_mutex);
471
472         write_lock_irqsave(&fm->lock, flags);
473         INIT_LIST_HEAD(&fence->ring);
474
475         /*
476          *  Avoid hitting BUG() for kernel-only fence objects.
477          */
478
479         INIT_LIST_HEAD(&fence->base.list);
480         fence->fence_class = fence_class;
481         fence->type = type;
482         fence->signaled_types = 0;
483         fence->waiting_types = 0;
484         fence->sequence = 0;
485         fence->dev = dev;
486         write_unlock_irqrestore(&fm->lock, flags);
487         if (fence_flags & DRM_FENCE_FLAG_EMIT) {
488                 ret = drm_fence_object_emit(fence, fence_flags,
489                                             fence->fence_class, type);
490         }
491         return ret;
492 }
493
494 int drm_fence_add_user_object(struct drm_file *priv,
495                               struct drm_fence_object *fence, int shareable)
496 {
497         struct drm_device *dev = priv->minor->dev;
498         int ret;
499
500         mutex_lock(&dev->struct_mutex);
501         ret = drm_add_user_object(priv, &fence->base, shareable);
502         if (ret)
503                 goto out;
504         atomic_inc(&fence->usage);
505         fence->base.type = drm_fence_type;
506         fence->base.remove = &drm_fence_object_destroy;
507         DRM_DEBUG("Fence 0x%08lx created\n", fence->base.hash.key);
508 out:
509         mutex_unlock(&dev->struct_mutex);
510         return ret;
511 }
512 EXPORT_SYMBOL(drm_fence_add_user_object);
513
514 int drm_fence_object_create(struct drm_device *dev, uint32_t fence_class,
515                             uint32_t type, unsigned flags,
516                             struct drm_fence_object **c_fence)
517 {
518         struct drm_fence_object *fence;
519         int ret;
520         struct drm_fence_manager *fm = &dev->fm;
521
522         fence = drm_ctl_calloc(1, sizeof(*fence), DRM_MEM_FENCE);
523         if (!fence) {
524                 DRM_ERROR("Out of memory creating fence object\n");
525                 return -ENOMEM;
526         }
527         ret = drm_fence_object_init(dev, fence_class, type, flags, fence);
528         if (ret) {
529                 drm_fence_usage_deref_unlocked(&fence);
530                 return ret;
531         }
532         *c_fence = fence;
533         atomic_inc(&fm->count);
534
535         return 0;
536 }
537 EXPORT_SYMBOL(drm_fence_object_create);
538
539 void drm_fence_manager_init(struct drm_device *dev)
540 {
541         struct drm_fence_manager *fm = &dev->fm;
542         struct drm_fence_class_manager *fence_class;
543         struct drm_fence_driver *fed = dev->driver->fence_driver;
544         int i;
545         unsigned long flags;
546
547         rwlock_init(&fm->lock);
548         write_lock_irqsave(&fm->lock, flags);
549         fm->initialized = 0;
550         if (!fed)
551             goto out_unlock;
552
553         fm->initialized = 1;
554         fm->num_classes = fed->num_classes;
555         BUG_ON(fm->num_classes > _DRM_FENCE_CLASSES);
556
557         for (i = 0; i < fm->num_classes; ++i) {
558             fence_class = &fm->fence_class[i];
559
560             memset(fence_class, 0, sizeof(*fence_class));
561             INIT_LIST_HEAD(&fence_class->ring);
562             DRM_INIT_WAITQUEUE(&fence_class->fence_queue);
563         }
564
565         atomic_set(&fm->count, 0);
566  out_unlock:
567         write_unlock_irqrestore(&fm->lock, flags);
568 }
569
570 void drm_fence_fill_arg(struct drm_fence_object *fence,
571                         struct drm_fence_arg *arg)
572 {
573         struct drm_device *dev = fence->dev;
574         struct drm_fence_manager *fm = &dev->fm;
575         unsigned long irq_flags;
576
577         read_lock_irqsave(&fm->lock, irq_flags);
578         arg->handle = fence->base.hash.key;
579         arg->fence_class = fence->fence_class;
580         arg->type = fence->type;
581         arg->signaled = fence->signaled_types;
582         arg->error = fence->error;
583         arg->sequence = fence->sequence;
584         read_unlock_irqrestore(&fm->lock, irq_flags);
585 }
586 EXPORT_SYMBOL(drm_fence_fill_arg);
587
588 void drm_fence_manager_takedown(struct drm_device *dev)
589 {
590 }
591
592 struct drm_fence_object *drm_lookup_fence_object(struct drm_file *priv,
593                                                  uint32_t handle)
594 {
595         struct drm_device *dev = priv->minor->dev;
596         struct drm_user_object *uo;
597         struct drm_fence_object *fence;
598
599         mutex_lock(&dev->struct_mutex);
600         uo = drm_lookup_user_object(priv, handle);
601         if (!uo || (uo->type != drm_fence_type)) {
602                 mutex_unlock(&dev->struct_mutex);
603                 return NULL;
604         }
605         fence = drm_fence_reference_locked(drm_user_object_entry(uo, struct drm_fence_object, base));
606         mutex_unlock(&dev->struct_mutex);
607         return fence;
608 }
609
610 int drm_fence_create_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv)
611 {
612         int ret;
613         struct drm_fence_manager *fm = &dev->fm;
614         struct drm_fence_arg *arg = data;
615         struct drm_fence_object *fence;
616         ret = 0;
617
618         if (!fm->initialized) {
619                 DRM_ERROR("The DRM driver does not support fencing.\n");
620                 return -EINVAL;
621         }
622
623         if (arg->flags & DRM_FENCE_FLAG_EMIT)
624                 LOCK_TEST_WITH_RETURN(dev, file_priv);
625         ret = drm_fence_object_create(dev, arg->fence_class,
626                                       arg->type, arg->flags, &fence);
627         if (ret)
628                 return ret;
629         ret = drm_fence_add_user_object(file_priv, fence,
630                                         arg->flags &
631                                         DRM_FENCE_FLAG_SHAREABLE);
632         if (ret) {
633                 drm_fence_usage_deref_unlocked(&fence);
634                 return ret;
635         }
636
637         /*
638          * usage > 0. No need to lock dev->struct_mutex;
639          */
640
641         arg->handle = fence->base.hash.key;
642
643         drm_fence_fill_arg(fence, arg);
644         drm_fence_usage_deref_unlocked(&fence);
645
646         return ret;
647 }
648
649 int drm_fence_reference_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv)
650 {
651         int ret;
652         struct drm_fence_manager *fm = &dev->fm;
653         struct drm_fence_arg *arg = data;
654         struct drm_fence_object *fence;
655         struct drm_user_object *uo;
656         ret = 0;
657
658         if (!fm->initialized) {
659                 DRM_ERROR("The DRM driver does not support fencing.\n");
660                 return -EINVAL;
661         }
662
663         ret = drm_user_object_ref(file_priv, arg->handle, drm_fence_type, &uo);
664         if (ret)
665                 return ret;
666         fence = drm_lookup_fence_object(file_priv, arg->handle);
667         drm_fence_fill_arg(fence, arg);
668         drm_fence_usage_deref_unlocked(&fence);
669
670         return ret;
671 }
672
673
674 int drm_fence_unreference_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv)
675 {
676         int ret;
677         struct drm_fence_manager *fm = &dev->fm;
678         struct drm_fence_arg *arg = data;
679         ret = 0;
680
681         if (!fm->initialized) {
682                 DRM_ERROR("The DRM driver does not support fencing.\n");
683                 return -EINVAL;
684         }
685
686         return drm_user_object_unref(file_priv, arg->handle, drm_fence_type);
687 }
688
689 int drm_fence_signaled_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv)
690 {
691         int ret;
692         struct drm_fence_manager *fm = &dev->fm;
693         struct drm_fence_arg *arg = data;
694         struct drm_fence_object *fence;
695         ret = 0;
696
697         if (!fm->initialized) {
698                 DRM_ERROR("The DRM driver does not support fencing.\n");
699                 return -EINVAL;
700         }
701
702         fence = drm_lookup_fence_object(file_priv, arg->handle);
703         if (!fence)
704                 return -EINVAL;
705
706         drm_fence_fill_arg(fence, arg);
707         drm_fence_usage_deref_unlocked(&fence);
708
709         return ret;
710 }
711
712 int drm_fence_flush_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv)
713 {
714         int ret;
715         struct drm_fence_manager *fm = &dev->fm;
716         struct drm_fence_arg *arg = data;
717         struct drm_fence_object *fence;
718         ret = 0;
719
720         if (!fm->initialized) {
721                 DRM_ERROR("The DRM driver does not support fencing.\n");
722                 return -EINVAL;
723         }
724
725         fence = drm_lookup_fence_object(file_priv, arg->handle);
726         if (!fence)
727                 return -EINVAL;
728         ret = drm_fence_object_flush(fence, arg->type);
729
730         drm_fence_fill_arg(fence, arg);
731         drm_fence_usage_deref_unlocked(&fence);
732
733         return ret;
734 }
735
736
737 int drm_fence_wait_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv)
738 {
739         int ret;
740         struct drm_fence_manager *fm = &dev->fm;
741         struct drm_fence_arg *arg = data;
742         struct drm_fence_object *fence;
743         ret = 0;
744
745         if (!fm->initialized) {
746                 DRM_ERROR("The DRM driver does not support fencing.\n");
747                 return -EINVAL;
748         }
749
750         fence = drm_lookup_fence_object(file_priv, arg->handle);
751         if (!fence)
752                 return -EINVAL;
753         ret = drm_fence_object_wait(fence,
754                                     arg->flags & DRM_FENCE_FLAG_WAIT_LAZY,
755                                     0, arg->type);
756
757         drm_fence_fill_arg(fence, arg);
758         drm_fence_usage_deref_unlocked(&fence);
759
760         return ret;
761 }
762
763
764 int drm_fence_emit_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv)
765 {
766         int ret;
767         struct drm_fence_manager *fm = &dev->fm;
768         struct drm_fence_arg *arg = data;
769         struct drm_fence_object *fence;
770         ret = 0;
771
772         if (!fm->initialized) {
773                 DRM_ERROR("The DRM driver does not support fencing.\n");
774                 return -EINVAL;
775         }
776
777         LOCK_TEST_WITH_RETURN(dev, file_priv);
778         fence = drm_lookup_fence_object(file_priv, arg->handle);
779         if (!fence)
780                 return -EINVAL;
781         ret = drm_fence_object_emit(fence, arg->flags, arg->fence_class,
782                                     arg->type);
783
784         drm_fence_fill_arg(fence, arg);
785         drm_fence_usage_deref_unlocked(&fence);
786
787         return ret;
788 }
789
790 int drm_fence_buffers_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv)
791 {
792         int ret;
793         struct drm_fence_manager *fm = &dev->fm;
794         struct drm_fence_arg *arg = data;
795         struct drm_fence_object *fence;
796         ret = 0;
797
798         if (!fm->initialized) {
799                 DRM_ERROR("The DRM driver does not support fencing.\n");
800                 return -EINVAL;
801         }
802
803         if (!dev->bm.initialized) {
804                 DRM_ERROR("Buffer object manager is not initialized\n");
805                 return -EINVAL;
806         }
807         LOCK_TEST_WITH_RETURN(dev, file_priv);
808         ret = drm_fence_buffer_objects(dev, NULL, arg->flags,
809                                        NULL, &fence);
810         if (ret)
811                 return ret;
812
813         if (!(arg->flags & DRM_FENCE_FLAG_NO_USER)) {
814                 ret = drm_fence_add_user_object(file_priv, fence,
815                                                 arg->flags &
816                                                 DRM_FENCE_FLAG_SHAREABLE);
817                 if (ret)
818                         return ret;
819         }
820
821         arg->handle = fence->base.hash.key;
822
823         drm_fence_fill_arg(fence, arg);
824         drm_fence_usage_deref_unlocked(&fence);
825
826         return ret;
827 }