1 // SPDX-License-Identifier: GPL-2.0 OR MIT
2 /**************************************************************************
3 *
4 * Copyright (c) 2009-2025 Broadcom. All Rights Reserved. The term
5 * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries.
6 *
7 **************************************************************************/
8
9 #include "vmwgfx_drv.h"
10
11 #define VMW_FENCE_WRAP (1 << 31)
12
13 struct vmw_fence_manager {
14 struct vmw_private *dev_priv;
15 spinlock_t lock;
16 struct list_head fence_list;
17 bool fifo_down;
18 u64 ctx;
19 };
20
21 struct vmw_user_fence {
22 struct ttm_base_object base;
23 struct vmw_fence_obj fence;
24 };
25
26 /**
27 * struct vmw_event_fence_action - fence callback that delivers a DRM event.
28 *
29 * @base: For use with dma_fence_add_callback(...)
30 * @event: A pointer to the pending event.
31 * @dev: Pointer to a struct drm_device so we can access the event stuff.
32 * @tv_sec: If non-null, the variable pointed to will be assigned
33 * current time tv_sec val when the fence signals.
34 * @tv_usec: Must be set if @tv_sec is set, and the variable pointed to will
35 * be assigned the current time tv_usec val when the fence signals.
36 */
37 struct vmw_event_fence_action {
38 struct dma_fence_cb base;
39
40 struct drm_pending_event *event;
41 struct drm_device *dev;
42
43 uint32_t *tv_sec;
44 uint32_t *tv_usec;
45 };
46
47 static struct vmw_fence_manager *
fman_from_fence(struct vmw_fence_obj * fence)48 fman_from_fence(struct vmw_fence_obj *fence)
49 {
50 return container_of(fence->base.extern_lock, struct vmw_fence_manager,
51 lock);
52 }
53
vmw_fence_obj_destroy(struct dma_fence * f)54 static void vmw_fence_obj_destroy(struct dma_fence *f)
55 {
56 struct vmw_fence_obj *fence =
57 container_of(f, struct vmw_fence_obj, base);
58 struct vmw_fence_manager *fman = fman_from_fence(fence);
59
60 if (!list_empty(&fence->head)) {
61 /* The fence manager still has an implicit reference to this
62 * fence via the fence list if head is set. Because the lock is
63 * required to be held when the fence manager updates the fence
64 * list either the fence will have been removed after we get
65 * the lock below or we can safely remove it and the fence
66 * manager will never see it. This implies the fence is being
67 * deleted without being signaled which is dubious but valid
68 * if there are no callbacks. The dma_fence code that calls
69 * this hook will warn about deleted unsignaled with callbacks
70 * so no need to warn again here.
71 */
72 spin_lock(&fman->lock);
73 list_del_init(&fence->head);
74 if (fence->waiter_added)
75 vmw_seqno_waiter_remove(fman->dev_priv);
76 spin_unlock(&fman->lock);
77 }
78 fence->destroy(fence);
79 }
80
vmw_fence_get_driver_name(struct dma_fence * f)81 static const char *vmw_fence_get_driver_name(struct dma_fence *f)
82 {
83 return "vmwgfx";
84 }
85
vmw_fence_get_timeline_name(struct dma_fence * f)86 static const char *vmw_fence_get_timeline_name(struct dma_fence *f)
87 {
88 return "svga";
89 }
90
91 /* When we toggle signaling for the SVGA device there is a race period from
92 * the time we first read the fence seqno to the time we enable interrupts.
93 * If we miss the interrupt for a fence during this period its likely the driver
94 * will stall. As a result we need to re-read the seqno after interrupts are
95 * enabled. If interrupts were already enabled we just increment the number of
96 * seqno waiters.
97 */
vmw_fence_enable_signaling(struct dma_fence * f)98 static bool vmw_fence_enable_signaling(struct dma_fence *f)
99 {
100 u32 seqno;
101 struct vmw_fence_obj *fence =
102 container_of(f, struct vmw_fence_obj, base);
103
104 struct vmw_fence_manager *fman = fman_from_fence(fence);
105 struct vmw_private *dev_priv = fman->dev_priv;
106 check_for_race:
107 seqno = vmw_fence_read(dev_priv);
108 if (seqno - fence->base.seqno < VMW_FENCE_WRAP) {
109 if (fence->waiter_added) {
110 vmw_seqno_waiter_remove(dev_priv);
111 fence->waiter_added = false;
112 }
113 return false;
114 } else if (!fence->waiter_added) {
115 fence->waiter_added = true;
116 if (vmw_seqno_waiter_add(dev_priv))
117 goto check_for_race;
118 }
119 return true;
120 }
121
122 static u32 __vmw_fences_update(struct vmw_fence_manager *fman);
123
124 static const struct dma_fence_ops vmw_fence_ops = {
125 .get_driver_name = vmw_fence_get_driver_name,
126 .get_timeline_name = vmw_fence_get_timeline_name,
127 .enable_signaling = vmw_fence_enable_signaling,
128 .release = vmw_fence_obj_destroy,
129 };
130
vmw_fence_manager_init(struct vmw_private * dev_priv)131 struct vmw_fence_manager *vmw_fence_manager_init(struct vmw_private *dev_priv)
132 {
133 struct vmw_fence_manager *fman = kzalloc_obj(*fman);
134
135 if (unlikely(!fman))
136 return NULL;
137
138 fman->dev_priv = dev_priv;
139 spin_lock_init(&fman->lock);
140 INIT_LIST_HEAD(&fman->fence_list);
141 fman->fifo_down = true;
142 fman->ctx = dma_fence_context_alloc(1);
143
144 return fman;
145 }
146
vmw_fence_manager_takedown(struct vmw_fence_manager * fman)147 void vmw_fence_manager_takedown(struct vmw_fence_manager *fman)
148 {
149 bool lists_empty;
150
151 spin_lock(&fman->lock);
152 lists_empty = list_empty(&fman->fence_list);
153 spin_unlock(&fman->lock);
154
155 BUG_ON(!lists_empty);
156 kfree(fman);
157 }
158
vmw_fence_obj_init(struct vmw_fence_manager * fman,struct vmw_fence_obj * fence,u32 seqno,void (* destroy)(struct vmw_fence_obj * fence))159 static int vmw_fence_obj_init(struct vmw_fence_manager *fman,
160 struct vmw_fence_obj *fence, u32 seqno,
161 void (*destroy) (struct vmw_fence_obj *fence))
162 {
163 int ret = 0;
164
165 dma_fence_init(&fence->base, &vmw_fence_ops, &fman->lock,
166 fman->ctx, seqno);
167 fence->destroy = destroy;
168
169 spin_lock(&fman->lock);
170 if (unlikely(fman->fifo_down)) {
171 ret = -EBUSY;
172 goto out_unlock;
173 }
174 /* This creates an implicit reference to the fence from the fence
175 * manager. It will be dropped when the fence is signaled which is
176 * expected to happen before deletion. The dtor has code to catch
177 * the rare deletion before signaling case.
178 */
179 list_add_tail(&fence->head, &fman->fence_list);
180
181 out_unlock:
182 spin_unlock(&fman->lock);
183 return ret;
184
185 }
186
__vmw_fences_update(struct vmw_fence_manager * fman)187 static u32 __vmw_fences_update(struct vmw_fence_manager *fman)
188 {
189 struct vmw_fence_obj *fence, *next_fence;
190 const bool cookie = dma_fence_begin_signalling();
191 const u32 seqno = vmw_fence_read(fman->dev_priv);
192
193 list_for_each_entry_safe(fence, next_fence, &fman->fence_list, head) {
194 if (seqno - fence->base.seqno < VMW_FENCE_WRAP) {
195 list_del_init(&fence->head);
196 if (fence->waiter_added) {
197 vmw_seqno_waiter_remove(fman->dev_priv);
198 fence->waiter_added = false;
199 }
200 dma_fence_signal_locked(&fence->base);
201 } else
202 break;
203 }
204 dma_fence_end_signalling(cookie);
205 atomic_set_release(&fman->dev_priv->last_read_seqno, seqno);
206 return seqno;
207 }
208
vmw_fences_update(struct vmw_fence_manager * fman)209 u32 vmw_fences_update(struct vmw_fence_manager *fman)
210 {
211 u32 seqno;
212 spin_lock(&fman->lock);
213 seqno = __vmw_fences_update(fman);
214 spin_unlock(&fman->lock);
215 return seqno;
216 }
217
vmw_fence_obj_signaled(struct vmw_fence_obj * fence)218 bool vmw_fence_obj_signaled(struct vmw_fence_obj *fence)
219 {
220 struct vmw_fence_manager *fman = fman_from_fence(fence);
221
222 if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->base.flags))
223 return true;
224
225 vmw_fences_update(fman);
226
227 return dma_fence_is_signaled(&fence->base);
228 }
229
vmw_fence_obj_wait(struct vmw_fence_obj * fence,bool lazy,bool interruptible,unsigned long timeout)230 int vmw_fence_obj_wait(struct vmw_fence_obj *fence, bool lazy,
231 bool interruptible, unsigned long timeout)
232 {
233 long ret = dma_fence_wait_timeout(&fence->base, interruptible, timeout);
234
235 if (likely(ret > 0))
236 return 0;
237 else if (ret == 0)
238 return -EBUSY;
239 else
240 return ret;
241 }
242
vmw_fence_destroy(struct vmw_fence_obj * fence)243 static void vmw_fence_destroy(struct vmw_fence_obj *fence)
244 {
245 dma_fence_free(&fence->base);
246 }
247
vmw_fence_create(struct vmw_fence_manager * fman,uint32_t seqno,struct vmw_fence_obj ** p_fence)248 int vmw_fence_create(struct vmw_fence_manager *fman,
249 uint32_t seqno,
250 struct vmw_fence_obj **p_fence)
251 {
252 struct vmw_fence_obj *fence;
253 int ret;
254
255 fence = kzalloc_obj(*fence);
256 if (unlikely(!fence))
257 return -ENOMEM;
258
259 ret = vmw_fence_obj_init(fman, fence, seqno, vmw_fence_destroy);
260 if (unlikely(ret != 0))
261 goto out_err_init;
262
263 *p_fence = fence;
264 return 0;
265
266 out_err_init:
267 kfree(fence);
268 return ret;
269 }
270
271
vmw_user_fence_destroy(struct vmw_fence_obj * fence)272 static void vmw_user_fence_destroy(struct vmw_fence_obj *fence)
273 {
274 struct vmw_user_fence *ufence =
275 container_of(fence, struct vmw_user_fence, fence);
276
277 ttm_base_object_kfree(ufence, base);
278 }
279
vmw_user_fence_base_release(struct ttm_base_object ** p_base)280 static void vmw_user_fence_base_release(struct ttm_base_object **p_base)
281 {
282 struct ttm_base_object *base = *p_base;
283 struct vmw_user_fence *ufence =
284 container_of(base, struct vmw_user_fence, base);
285 struct vmw_fence_obj *fence = &ufence->fence;
286
287 *p_base = NULL;
288 vmw_fence_obj_unreference(&fence);
289 }
290
vmw_user_fence_create(struct drm_file * file_priv,struct vmw_fence_manager * fman,uint32_t seqno,struct vmw_fence_obj ** p_fence,uint32_t * p_handle)291 int vmw_user_fence_create(struct drm_file *file_priv,
292 struct vmw_fence_manager *fman,
293 uint32_t seqno,
294 struct vmw_fence_obj **p_fence,
295 uint32_t *p_handle)
296 {
297 struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
298 struct vmw_user_fence *ufence;
299 struct vmw_fence_obj *tmp;
300 int ret;
301
302 ufence = kzalloc_obj(*ufence);
303 if (unlikely(!ufence)) {
304 ret = -ENOMEM;
305 goto out_no_object;
306 }
307
308 ret = vmw_fence_obj_init(fman, &ufence->fence, seqno,
309 vmw_user_fence_destroy);
310 if (unlikely(ret != 0)) {
311 kfree(ufence);
312 goto out_no_object;
313 }
314
315 /*
316 * The base object holds a reference which is freed in
317 * vmw_user_fence_base_release.
318 */
319 tmp = vmw_fence_obj_reference(&ufence->fence);
320
321 ret = ttm_base_object_init(tfile, &ufence->base, false,
322 VMW_RES_FENCE,
323 &vmw_user_fence_base_release);
324
325
326 if (unlikely(ret != 0)) {
327 /*
328 * Free the base object's reference
329 */
330 vmw_fence_obj_unreference(&tmp);
331 goto out_err;
332 }
333
334 *p_fence = &ufence->fence;
335 *p_handle = ufence->base.handle;
336
337 return 0;
338 out_err:
339 tmp = &ufence->fence;
340 vmw_fence_obj_unreference(&tmp);
341 out_no_object:
342 return ret;
343 }
344
345 /*
346 * vmw_fence_fifo_down - signal all unsignaled fence objects.
347 */
348
vmw_fence_fifo_down(struct vmw_fence_manager * fman)349 void vmw_fence_fifo_down(struct vmw_fence_manager *fman)
350 {
351 int ret;
352
353 /*
354 * The list may be altered while we traverse it, so always
355 * restart when we've released the fman->lock.
356 */
357
358 spin_lock(&fman->lock);
359 fman->fifo_down = true;
360 while (!list_empty(&fman->fence_list)) {
361 struct vmw_fence_obj *fence =
362 list_entry(fman->fence_list.prev, struct vmw_fence_obj,
363 head);
364 dma_fence_get(&fence->base);
365 spin_unlock(&fman->lock);
366
367 ret = vmw_fence_obj_wait(fence, false, false,
368 VMW_FENCE_WAIT_TIMEOUT);
369
370 spin_lock(&fman->lock);
371 if (unlikely(ret != 0)) {
372 bool cookie = dma_fence_begin_signalling();
373
374 list_del_init(&fence->head);
375 if (fence->waiter_added) {
376 vmw_seqno_waiter_remove(fman->dev_priv);
377 fence->waiter_added = false;
378 }
379 dma_fence_signal_locked(&fence->base);
380 dma_fence_end_signalling(cookie);
381 }
382
383 BUG_ON(!list_empty(&fence->head));
384 spin_unlock(&fman->lock);
385
386 dma_fence_put(&fence->base);
387
388 spin_lock(&fman->lock);
389 }
390 spin_unlock(&fman->lock);
391 }
392
vmw_fence_fifo_up(struct vmw_fence_manager * fman)393 void vmw_fence_fifo_up(struct vmw_fence_manager *fman)
394 {
395 spin_lock(&fman->lock);
396 fman->fifo_down = false;
397 spin_unlock(&fman->lock);
398 }
399
400
401 /**
402 * vmw_fence_obj_lookup - Look up a user-space fence object
403 *
404 * @tfile: A struct ttm_object_file identifying the caller.
405 * @handle: A handle identifying the fence object.
406 * @return: A struct vmw_user_fence base ttm object on success or
407 * an error pointer on failure.
408 *
409 * The fence object is looked up and type-checked. The caller needs
410 * to have opened the fence object first, but since that happens on
411 * creation and fence objects aren't shareable, that's not an
412 * issue currently.
413 */
414 static struct ttm_base_object *
vmw_fence_obj_lookup(struct ttm_object_file * tfile,u32 handle)415 vmw_fence_obj_lookup(struct ttm_object_file *tfile, u32 handle)
416 {
417 struct ttm_base_object *base = ttm_base_object_lookup(tfile, handle);
418
419 if (!base) {
420 pr_err("Invalid fence object handle 0x%08lx.\n",
421 (unsigned long)handle);
422 return ERR_PTR(-EINVAL);
423 }
424
425 if (base->refcount_release != vmw_user_fence_base_release) {
426 pr_err("Invalid fence object handle 0x%08lx.\n",
427 (unsigned long)handle);
428 ttm_base_object_unref(&base);
429 return ERR_PTR(-EINVAL);
430 }
431
432 return base;
433 }
434
435
vmw_fence_obj_wait_ioctl(struct drm_device * dev,void * data,struct drm_file * file_priv)436 int vmw_fence_obj_wait_ioctl(struct drm_device *dev, void *data,
437 struct drm_file *file_priv)
438 {
439 struct drm_vmw_fence_wait_arg *arg =
440 (struct drm_vmw_fence_wait_arg *)data;
441 unsigned long timeout;
442 struct ttm_base_object *base;
443 struct vmw_fence_obj *fence;
444 struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
445 int ret;
446 uint64_t wait_timeout = ((uint64_t)arg->timeout_us * HZ);
447
448 /*
449 * 64-bit division not present on 32-bit systems, so do an
450 * approximation. (Divide by 1000000).
451 */
452
453 wait_timeout = (wait_timeout >> 20) + (wait_timeout >> 24) -
454 (wait_timeout >> 26);
455
456 if (!arg->cookie_valid) {
457 arg->cookie_valid = 1;
458 arg->kernel_cookie = jiffies + wait_timeout;
459 }
460
461 base = vmw_fence_obj_lookup(tfile, arg->handle);
462 if (IS_ERR(base))
463 return PTR_ERR(base);
464
465 fence = &(container_of(base, struct vmw_user_fence, base)->fence);
466
467 timeout = jiffies;
468 if (time_after_eq(timeout, (unsigned long)arg->kernel_cookie)) {
469 ret = ((vmw_fence_obj_signaled(fence)) ?
470 0 : -EBUSY);
471 goto out;
472 }
473
474 timeout = (unsigned long)arg->kernel_cookie - timeout;
475
476 ret = vmw_fence_obj_wait(fence, arg->lazy, true, timeout);
477
478 out:
479 ttm_base_object_unref(&base);
480
481 /*
482 * Optionally unref the fence object.
483 */
484
485 if (ret == 0 && (arg->wait_options & DRM_VMW_WAIT_OPTION_UNREF))
486 return ttm_ref_object_base_unref(tfile, arg->handle);
487 return ret;
488 }
489
vmw_fence_obj_signaled_ioctl(struct drm_device * dev,void * data,struct drm_file * file_priv)490 int vmw_fence_obj_signaled_ioctl(struct drm_device *dev, void *data,
491 struct drm_file *file_priv)
492 {
493 struct drm_vmw_fence_signaled_arg *arg =
494 (struct drm_vmw_fence_signaled_arg *) data;
495 struct ttm_base_object *base;
496 struct vmw_fence_obj *fence;
497 struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
498 struct vmw_private *dev_priv = vmw_priv(dev);
499
500 base = vmw_fence_obj_lookup(tfile, arg->handle);
501 if (IS_ERR(base))
502 return PTR_ERR(base);
503
504 fence = &(container_of(base, struct vmw_user_fence, base)->fence);
505
506 arg->signaled = vmw_fence_obj_signaled(fence);
507
508 arg->signaled_flags = arg->flags;
509 arg->passed_seqno = atomic_read_acquire(&dev_priv->last_read_seqno);
510
511 ttm_base_object_unref(&base);
512
513 return 0;
514 }
515
516
vmw_fence_obj_unref_ioctl(struct drm_device * dev,void * data,struct drm_file * file_priv)517 int vmw_fence_obj_unref_ioctl(struct drm_device *dev, void *data,
518 struct drm_file *file_priv)
519 {
520 struct drm_vmw_fence_arg *arg =
521 (struct drm_vmw_fence_arg *) data;
522
523 return ttm_ref_object_base_unref(vmw_fpriv(file_priv)->tfile,
524 arg->handle);
525 }
526
527 /**
528 * vmw_event_fence_action_seq_passed
529 *
530 * @f: The struct dma_fence which provides timestamp for the action event
531 * @cb: The struct dma_fence_cb callback for the action event.
532 *
533 * This function is called when the seqno of the fence has passed
534 * and it is always called from atomic context.
535 * It queues the event on the submitter's event list.
536 */
vmw_event_fence_action_seq_passed(struct dma_fence * f,struct dma_fence_cb * cb)537 static void vmw_event_fence_action_seq_passed(struct dma_fence *f,
538 struct dma_fence_cb *cb)
539 {
540 struct vmw_event_fence_action *eaction =
541 container_of(cb, struct vmw_event_fence_action, base);
542 struct drm_device *dev = eaction->dev;
543 struct drm_pending_event *event = eaction->event;
544
545 if (unlikely(event == NULL))
546 return;
547
548 spin_lock_irq(&dev->event_lock);
549
550 if (likely(eaction->tv_sec != NULL)) {
551 struct timespec64 ts;
552
553 ts = ktime_to_timespec64(f->timestamp);
554 /* monotonic time, so no y2038 overflow */
555 *eaction->tv_sec = ts.tv_sec;
556 *eaction->tv_usec = ts.tv_nsec / NSEC_PER_USEC;
557 }
558
559 drm_send_event_locked(dev, eaction->event);
560 eaction->event = NULL;
561 spin_unlock_irq(&dev->event_lock);
562 dma_fence_put(f);
563 kfree(eaction);
564 }
565
566 /**
567 * vmw_event_fence_action_queue - Post an event for sending when a fence
568 * object seqno has passed.
569 *
570 * @file_priv: The file connection on which the event should be posted.
571 * @fence: The fence object on which to post the event.
572 * @event: Event to be posted. This event should've been alloced
573 * using k[mz]alloc, and should've been completely initialized.
574 * @tv_sec: If non-null, the variable pointed to will be assigned
575 * current time tv_sec val when the fence signals.
576 * @tv_usec: Must be set if @tv_sec is set, and the variable pointed to will
577 * be assigned the current time tv_usec val when the fence signals.
578 * @interruptible: Interruptible waits if possible.
579 *
580 * As a side effect, the object pointed to by @event may have been
581 * freed when this function returns. If this function returns with
582 * an error code, the caller needs to free that object.
583 */
584
vmw_event_fence_action_queue(struct drm_file * file_priv,struct vmw_fence_obj * fence,struct drm_pending_event * event,uint32_t * tv_sec,uint32_t * tv_usec,bool interruptible)585 int vmw_event_fence_action_queue(struct drm_file *file_priv,
586 struct vmw_fence_obj *fence,
587 struct drm_pending_event *event,
588 uint32_t *tv_sec,
589 uint32_t *tv_usec,
590 bool interruptible)
591 {
592 struct vmw_event_fence_action *eaction;
593 struct vmw_fence_manager *fman = fman_from_fence(fence);
594
595 eaction = kzalloc_obj(*eaction);
596 if (unlikely(!eaction))
597 return -ENOMEM;
598
599 eaction->event = event;
600 eaction->dev = &fman->dev_priv->drm;
601 eaction->tv_sec = tv_sec;
602 eaction->tv_usec = tv_usec;
603
604 vmw_fence_obj_reference(fence); // Dropped in CB
605 if (dma_fence_add_callback(&fence->base, &eaction->base,
606 vmw_event_fence_action_seq_passed) < 0)
607 vmw_event_fence_action_seq_passed(&fence->base, &eaction->base);
608 return 0;
609 }
610
611 struct vmw_event_fence_pending {
612 struct drm_pending_event base;
613 struct drm_vmw_event_fence event;
614 };
615
vmw_event_fence_action_create(struct drm_file * file_priv,struct vmw_fence_obj * fence,uint32_t flags,uint64_t user_data,bool interruptible)616 static int vmw_event_fence_action_create(struct drm_file *file_priv,
617 struct vmw_fence_obj *fence,
618 uint32_t flags,
619 uint64_t user_data,
620 bool interruptible)
621 {
622 struct vmw_event_fence_pending *event;
623 struct vmw_fence_manager *fman = fman_from_fence(fence);
624 struct drm_device *dev = &fman->dev_priv->drm;
625 int ret;
626
627 event = kzalloc_obj(*event);
628 if (unlikely(!event)) {
629 DRM_ERROR("Failed to allocate an event.\n");
630 ret = -ENOMEM;
631 goto out_no_space;
632 }
633
634 event->event.base.type = DRM_VMW_EVENT_FENCE_SIGNALED;
635 event->event.base.length = sizeof(event->event);
636 event->event.user_data = user_data;
637
638 ret = drm_event_reserve_init(dev, file_priv, &event->base, &event->event.base);
639
640 if (unlikely(ret != 0)) {
641 DRM_ERROR("Failed to allocate event space for this file.\n");
642 kfree(event);
643 goto out_no_space;
644 }
645
646 if (flags & DRM_VMW_FE_FLAG_REQ_TIME)
647 ret = vmw_event_fence_action_queue(file_priv, fence,
648 &event->base,
649 &event->event.tv_sec,
650 &event->event.tv_usec,
651 interruptible);
652 else
653 ret = vmw_event_fence_action_queue(file_priv, fence,
654 &event->base,
655 NULL,
656 NULL,
657 interruptible);
658 if (ret != 0)
659 goto out_no_queue;
660
661 return 0;
662
663 out_no_queue:
664 drm_event_cancel_free(dev, &event->base);
665 out_no_space:
666 return ret;
667 }
668
vmw_fence_event_ioctl(struct drm_device * dev,void * data,struct drm_file * file_priv)669 int vmw_fence_event_ioctl(struct drm_device *dev, void *data,
670 struct drm_file *file_priv)
671 {
672 struct vmw_private *dev_priv = vmw_priv(dev);
673 struct drm_vmw_fence_event_arg *arg =
674 (struct drm_vmw_fence_event_arg *) data;
675 struct vmw_fence_obj *fence = NULL;
676 struct vmw_fpriv *vmw_fp = vmw_fpriv(file_priv);
677 struct ttm_object_file *tfile = vmw_fp->tfile;
678 struct drm_vmw_fence_rep __user *user_fence_rep =
679 (struct drm_vmw_fence_rep __user *)(unsigned long)
680 arg->fence_rep;
681 uint32_t handle;
682 int ret;
683
684 /*
685 * Look up an existing fence object,
686 * and if user-space wants a new reference,
687 * add one.
688 */
689 if (arg->handle) {
690 struct ttm_base_object *base =
691 vmw_fence_obj_lookup(tfile, arg->handle);
692
693 if (IS_ERR(base))
694 return PTR_ERR(base);
695
696 fence = &(container_of(base, struct vmw_user_fence,
697 base)->fence);
698 (void) vmw_fence_obj_reference(fence);
699
700 if (user_fence_rep != NULL) {
701 ret = ttm_ref_object_add(vmw_fp->tfile, base,
702 NULL, false);
703 if (unlikely(ret != 0)) {
704 DRM_ERROR("Failed to reference a fence "
705 "object.\n");
706 goto out_no_ref_obj;
707 }
708 handle = base->handle;
709 }
710 ttm_base_object_unref(&base);
711 }
712
713 /*
714 * Create a new fence object.
715 */
716 if (!fence) {
717 ret = vmw_execbuf_fence_commands(file_priv, dev_priv,
718 &fence,
719 (user_fence_rep) ?
720 &handle : NULL);
721 if (unlikely(ret != 0)) {
722 DRM_ERROR("Fence event failed to create fence.\n");
723 return ret;
724 }
725 }
726
727 BUG_ON(fence == NULL);
728
729 ret = vmw_event_fence_action_create(file_priv, fence,
730 arg->flags,
731 arg->user_data,
732 true);
733 if (unlikely(ret != 0)) {
734 if (ret != -ERESTARTSYS)
735 DRM_ERROR("Failed to attach event to fence.\n");
736 goto out_no_create;
737 }
738
739 vmw_execbuf_copy_fence_user(dev_priv, vmw_fp, 0, user_fence_rep, fence,
740 handle, -1);
741 vmw_fence_obj_unreference(&fence);
742 return 0;
743 out_no_create:
744 if (user_fence_rep != NULL)
745 ttm_ref_object_base_unref(tfile, handle);
746 out_no_ref_obj:
747 vmw_fence_obj_unreference(&fence);
748 return ret;
749 }
750