3 * @Title PowerVR Linux fence interface
4 * @Codingstyle LinuxKernel
5 * @Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
6 * @License Dual MIT/GPLv2
8 * The contents of this file are subject to the MIT license as set out below.
10 * Permission is hereby granted, free of charge, to any person obtaining a copy
11 * of this software and associated documentation files (the "Software"), to deal
12 * in the Software without restriction, including without limitation the rights
13 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 * copies of the Software, and to permit persons to whom the Software is
15 * furnished to do so, subject to the following conditions:
17 * The above copyright notice and this permission notice shall be included in
18 * all copies or substantial portions of the Software.
20 * Alternatively, the contents of this file may be used under the terms of
21 * the GNU General Public License Version 2 ("GPL") in which case the provisions
22 * of GPL are applicable instead of those above.
24 * If you wish to allow use of your version of this file only under the terms of
25 * GPL, and not to allow others to use your version of this file under the terms
26 * of the MIT license, indicate your decision by deleting the provisions above
27 * and replace them with the notice and other provisions required by GPL as set
28 * out in the file called "GPL-COPYING" included in this distribution. If you do
29 * not delete the provisions above, a recipient may use your version of this file
30 * under the terms of either the MIT license or GPL.
32 * This License is also included in this distribution in the file called
35 * EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
36 * PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
37 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
38 * PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
39 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
40 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
41 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
44 #include <linux/kernel.h>
45 #include <linux/jiffies.h>
46 #include <linux/module.h>
47 #include <linux/slab.h>
49 #include "pvr_fence.h"
50 #include "services_kernel_client.h"
51 #include "sync_checkpoint_external.h"
53 #define CREATE_TRACE_POINTS
54 #include "pvr_fence_trace.h"
56 /* This header must always be included last */
57 #include "kernel_compatibility.h"
59 /* Global kmem_cache for pvr_fence object allocations */
60 static struct kmem_cache *pvr_fence_cache;
61 static DEFINE_MUTEX(pvr_fence_cache_mutex);
62 static u32 pvr_fence_cache_refcount;
64 #define PVR_DUMPDEBUG_LOG(pfnDumpDebugPrintf, pvDumpDebugFile, fmt, ...) \
66 if (pfnDumpDebugPrintf) \
67 pfnDumpDebugPrintf(pvDumpDebugFile, fmt, \
70 pr_err(fmt "\n", ## __VA_ARGS__); \
74 pvr_fence_sync_signal(struct pvr_fence *pvr_fence, u32 fence_sync_flags)
76 SyncCheckpointSignal(pvr_fence->sync_checkpoint, fence_sync_flags);
80 pvr_fence_sync_is_signaled(struct pvr_fence *pvr_fence, u32 fence_sync_flags)
82 return SyncCheckpointIsSignalled(pvr_fence->sync_checkpoint,
87 pvr_fence_sync_value(struct pvr_fence *pvr_fence)
89 if (SyncCheckpointIsErrored(pvr_fence->sync_checkpoint,
90 PVRSRV_FENCE_FLAG_SUPPRESS_HWP_PKT))
91 return PVRSRV_SYNC_CHECKPOINT_ERRORED;
92 else if (SyncCheckpointIsSignalled(pvr_fence->sync_checkpoint,
93 PVRSRV_FENCE_FLAG_SUPPRESS_HWP_PKT))
94 return PVRSRV_SYNC_CHECKPOINT_SIGNALLED;
96 return PVRSRV_SYNC_CHECKPOINT_ACTIVE;
100 pvr_fence_context_check_status(struct work_struct *data)
102 PVRSRVCheckStatus(NULL);
106 pvr_context_value_str(struct pvr_fence_context *fctx, char *str, int size)
109 "%u ctx=%llu refs=%u",
110 atomic_read(&fctx->fence_seqno),
112 refcount_read(&fctx->kref.refcount));
116 pvr_fence_context_fences_dump(struct pvr_fence_context *fctx,
117 DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
118 void *pvDumpDebugFile)
120 struct pvr_fence *pvr_fence;
124 spin_lock_irqsave(&fctx->list_lock, flags);
125 pvr_context_value_str(fctx, value, sizeof(value));
126 PVR_DUMPDEBUG_LOG(pfnDumpDebugPrintf, pvDumpDebugFile,
127 "%s: @%s", fctx->name, value);
128 list_for_each_entry(pvr_fence, &fctx->fence_list, fence_head) {
129 struct dma_fence *fence = pvr_fence->fence;
130 const char *timeline_value_str = "unknown timeline value";
131 const char *fence_value_str = "unknown fence value";
133 pvr_fence->base.ops->fence_value_str(&pvr_fence->base, value,
135 PVR_DUMPDEBUG_LOG(pfnDumpDebugPrintf, pvDumpDebugFile,
138 if (is_pvr_fence(fence))
141 if (fence->ops->timeline_value_str) {
142 fence->ops->timeline_value_str(fence, value,
144 timeline_value_str = value;
147 PVR_DUMPDEBUG_LOG(pfnDumpDebugPrintf, pvDumpDebugFile,
148 " | %s: %s (driver: %s)",
149 fence->ops->get_timeline_name(fence),
151 fence->ops->get_driver_name(fence));
153 if (fence->ops->fence_value_str) {
154 fence->ops->fence_value_str(fence, value,
156 fence_value_str = value;
159 PVR_DUMPDEBUG_LOG(pfnDumpDebugPrintf, pvDumpDebugFile,
160 " | @%s (foreign)", value);
162 spin_unlock_irqrestore(&fctx->list_lock, flags);
165 static inline unsigned int
166 pvr_fence_context_seqno_next(struct pvr_fence_context *fctx)
168 return atomic_inc_return(&fctx->fence_seqno) - 1;
171 /* This function prepends seqno to fence name */
173 pvr_fence_prepare_name(char *fence_name, size_t fence_name_size,
174 const char *name, unsigned int seqno)
178 len = OSStringUINT32ToStr(fence_name, fence_name_size, seqno);
179 if (likely((len > 0) && (fence_name_size >= (len + 1)))) {
180 fence_name[len] = '-';
181 fence_name[len + 1] = '\0';
183 strlcat(fence_name, name, fence_name_size);
187 pvr_fence_sched_free(struct rcu_head *rcu)
189 struct pvr_fence *pvr_fence = container_of(rcu, struct pvr_fence, rcu);
191 kmem_cache_free(pvr_fence_cache, pvr_fence);
195 pvr_fence_context_free_deferred(struct pvr_fence_context *fctx)
197 struct pvr_fence *pvr_fence, *tmp;
198 LIST_HEAD(deferred_free_list);
201 spin_lock_irqsave(&fctx->list_lock, flags);
202 list_for_each_entry_safe(pvr_fence, tmp,
203 &fctx->deferred_free_list,
205 list_move(&pvr_fence->fence_head, &deferred_free_list);
206 spin_unlock_irqrestore(&fctx->list_lock, flags);
208 list_for_each_entry_safe(pvr_fence, tmp,
211 list_del(&pvr_fence->fence_head);
212 SyncCheckpointFree(pvr_fence->sync_checkpoint);
213 call_rcu(&pvr_fence->rcu, pvr_fence_sched_free);
214 module_put(THIS_MODULE);
219 pvr_fence_context_free_deferred_callback(void *data)
221 struct pvr_fence_context *fctx = (struct pvr_fence_context *)data;
224 * Free up any fence objects we have deferred freeing.
226 pvr_fence_context_free_deferred(fctx);
230 pvr_fence_context_signal_fences(void *data)
232 struct pvr_fence_context *fctx = (struct pvr_fence_context *)data;
233 struct pvr_fence *pvr_fence, *tmp;
234 unsigned long flags1;
236 LIST_HEAD(signal_list);
239 * We can't call fence_signal while holding the lock as we can end up
240 * in a situation whereby pvr_fence_foreign_signal_sync, which also
241 * takes the list lock, ends up being called as a result of the
242 * fence_signal below, i.e. fence_signal(fence) -> fence->callback()
243 * -> fence_signal(foreign_fence) -> foreign_fence->callback() where
244 * the foreign_fence callback is pvr_fence_foreign_signal_sync.
246 * So extract the items we intend to signal and add them to their own
249 spin_lock_irqsave(&fctx->list_lock, flags1);
250 list_for_each_entry_safe(pvr_fence, tmp, &fctx->signal_list, signal_head) {
251 if (pvr_fence_sync_is_signaled(pvr_fence, PVRSRV_FENCE_FLAG_SUPPRESS_HWP_PKT))
252 list_move_tail(&pvr_fence->signal_head, &signal_list);
254 spin_unlock_irqrestore(&fctx->list_lock, flags1);
256 list_for_each_entry_safe(pvr_fence, tmp, &signal_list, signal_head) {
258 PVR_FENCE_TRACE(&pvr_fence->base, "signalled fence (%s)\n",
260 trace_pvr_fence_signal_fence(pvr_fence);
261 spin_lock_irqsave(&pvr_fence->fctx->list_lock, flags1);
262 list_del(&pvr_fence->signal_head);
263 spin_unlock_irqrestore(&pvr_fence->fctx->list_lock, flags1);
264 dma_fence_signal(pvr_fence->fence);
265 dma_fence_put(pvr_fence->fence);
269 * Take this opportunity to free up any fence objects we
270 * have deferred freeing.
272 pvr_fence_context_free_deferred(fctx);
276 pvr_fence_context_signal_fences_nohw(void *data)
278 pvr_fence_context_signal_fences(data);
282 pvr_fence_context_destroy_internal(struct pvr_fence_context *fctx)
284 pvr_fence_context_free_deferred(fctx);
286 if (WARN_ON(!list_empty_careful(&fctx->fence_list)))
287 pvr_fence_context_fences_dump(fctx, NULL, NULL);
289 PVRSRVUnregisterCmdCompleteNotify(fctx->cmd_complete_handle);
291 // wait for all fences to be freed before kmem_cache_destroy() is called
294 /* Destroy pvr_fence object cache, if no one is using it */
295 WARN_ON(pvr_fence_cache == NULL);
296 mutex_lock(&pvr_fence_cache_mutex);
297 if (--pvr_fence_cache_refcount == 0)
298 kmem_cache_destroy(pvr_fence_cache);
299 mutex_unlock(&pvr_fence_cache_mutex);
305 pvr_fence_context_unregister_dbg(void *dbg_request_handle)
307 PVRSRVUnregisterDeviceDbgRequestNotify(dbg_request_handle);
311 pvr_fence_foreign_context_destroy_work(struct work_struct *data)
313 struct pvr_fence_context *fctx =
314 container_of(data, struct pvr_fence_context, destroy_work);
316 pvr_fence_context_destroy_internal(fctx);
320 pvr_fence_context_destroy_work(struct work_struct *data)
322 struct pvr_fence_context *fctx =
323 container_of(data, struct pvr_fence_context, destroy_work);
325 pvr_fence_context_unregister_dbg(fctx->dbg_request_handle);
326 pvr_fence_context_destroy_internal(fctx);
330 pvr_fence_context_debug_request(void *data, u32 verbosity,
331 DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
332 void *pvDumpDebugFile)
334 struct pvr_fence_context *fctx = (struct pvr_fence_context *)data;
336 if (DD_VERB_LVL_ENABLED(verbosity, DEBUG_REQUEST_VERBOSITY_MEDIUM))
337 pvr_fence_context_fences_dump(fctx, pfnDumpDebugPrintf,
341 static struct pvr_fence_context *
342 pvr_fence_context_create_internal(struct workqueue_struct *fence_status_wq,
344 work_func_t destroy_callback)
346 struct pvr_fence_context *fctx;
347 PVRSRV_ERROR srv_err;
349 fctx = kzalloc(sizeof(*fctx), GFP_KERNEL);
353 spin_lock_init(&fctx->lock);
354 atomic_set(&fctx->fence_seqno, 0);
355 INIT_WORK(&fctx->check_status_work, pvr_fence_context_check_status);
356 INIT_WORK(&fctx->destroy_work, destroy_callback);
357 spin_lock_init(&fctx->list_lock);
358 INIT_LIST_HEAD(&fctx->signal_list);
359 INIT_LIST_HEAD(&fctx->fence_list);
360 INIT_LIST_HEAD(&fctx->deferred_free_list);
362 fctx->fence_wq = fence_status_wq;
364 fctx->fence_context = dma_fence_context_alloc(1);
365 strlcpy(fctx->name, name, sizeof(fctx->name));
367 srv_err = PVRSRVRegisterCmdCompleteNotify(&fctx->cmd_complete_handle,
368 pvr_fence_context_signal_fences,
370 if (srv_err != PVRSRV_OK) {
371 pr_err("%s: failed to register command complete callback (%s)\n",
372 __func__, PVRSRVGetErrorString(srv_err));
376 /* Create pvr_fence object cache, if not already created */
377 mutex_lock(&pvr_fence_cache_mutex);
378 if (pvr_fence_cache_refcount == 0) {
379 pvr_fence_cache = KMEM_CACHE(pvr_fence, 0);
380 if (!pvr_fence_cache) {
381 pr_err("%s: failed to allocate pvr_fence cache\n",
383 mutex_unlock(&pvr_fence_cache_mutex);
384 goto err_unregister_cmd_complete_notify;
387 pvr_fence_cache_refcount++;
388 mutex_unlock(&pvr_fence_cache_mutex);
390 kref_init(&fctx->kref);
392 PVR_FENCE_CTX_TRACE(fctx, "created fence context (%s)\n", name);
393 trace_pvr_fence_context_create(fctx);
397 err_unregister_cmd_complete_notify:
398 PVRSRVUnregisterCmdCompleteNotify(fctx->cmd_complete_handle);
405 * pvr_fence_context_register_dbg - registers the debug handler for a
408 * @dbg_request_handle: handle used to keep a reference for deregister
409 * @dev: device to attach the debug notifier.
410 * @pvr_fence_context: context used as data to the callback for debug
412 * Registers a debug notifier for a given context for a given device.
414 * Returns PVRSRV_OK if successful.
416 PVRSRV_ERROR pvr_fence_context_register_dbg(void *dbg_request_handle,
418 struct pvr_fence_context *fctx)
420 PVRSRV_ERROR srv_err;
422 srv_err = PVRSRVRegisterDeviceDbgRequestNotify(dbg_request_handle,
424 pvr_fence_context_debug_request,
425 DEBUG_REQUEST_LINUXFENCE,
427 if (srv_err != PVRSRV_OK) {
428 pr_err("%s: failed to register debug request callback (%s)\n",
429 __func__, PVRSRVGetErrorString(srv_err));
436 * pvr_fence_foreign_context_create - creates a PVR fence context
437 * @fence_status_wq: linux workqueue used to signal foreign fences
438 * @name: context name (used for debugging)
440 * Creates a PVR foreign fence context that can be used to create PVR fences
441 * or to create PVR fences from an existing fence.
443 * pvr_fence_context_destroy should be called to clean up the fence context.
445 * Returns NULL if a context cannot be created.
447 struct pvr_fence_context *
448 pvr_fence_foreign_context_create(struct workqueue_struct *fence_status_wq,
451 return pvr_fence_context_create_internal(fence_status_wq, name,
452 pvr_fence_foreign_context_destroy_work);
456 * pvr_fence_context_create - creates a PVR fence context
457 * @dev_cookie: services device cookie
458 * @fence_status_wq: Status workqueue to queue fence update CBs.
459 * @name: context name (used for debugging)
461 * Creates a PVR fence context that can be used to create PVR fences or to
462 * create PVR fences from an existing fence.
464 * pvr_fence_context_destroy should be called to clean up the fence context.
466 * Returns NULL if a context cannot be created.
468 struct pvr_fence_context *
469 pvr_fence_context_create(void *dev_cookie,
470 struct workqueue_struct *fence_status_wq,
473 struct pvr_fence_context *fctx;
476 fctx = pvr_fence_context_create_internal(fence_status_wq, name,
477 pvr_fence_context_destroy_work);
479 pr_err("%s: failed to create fence context", __func__);
483 eError = pvr_fence_context_register_dbg(&fctx->dbg_request_handle,
486 if (eError != PVRSRV_OK) {
487 pr_err("%s: failed to register fence context debug (%s)\n",
488 __func__, PVRSRVGetErrorString(eError));
489 goto err_destroy_ctx;
495 pvr_fence_context_destroy(fctx);
500 static void pvr_fence_context_destroy_kref(struct kref *kref)
502 struct pvr_fence_context *fctx =
503 container_of(kref, struct pvr_fence_context, kref);
505 PVR_FENCE_CTX_TRACE(fctx, "destroyed fence context (%s)\n", fctx->name);
507 trace_pvr_fence_context_destroy_kref(fctx);
509 schedule_work(&fctx->destroy_work);
513 * pvr_fence_context_destroy - destroys a context
514 * @fctx: PVR fence context to destroy
516 * Destroys a PVR fence context with the expectation that all fences have been
520 pvr_fence_context_destroy(struct pvr_fence_context *fctx)
522 trace_pvr_fence_context_destroy(fctx);
524 kref_put(&fctx->kref, pvr_fence_context_destroy_kref);
528 pvr_fence_get_driver_name(struct dma_fence *fence)
530 return PVR_LDM_DRIVER_REGISTRATION_NAME;
534 pvr_fence_get_timeline_name(struct dma_fence *fence)
536 struct pvr_fence *pvr_fence = to_pvr_fence(fence);
539 return pvr_fence->fctx->name;
544 void pvr_fence_fence_value_str(struct dma_fence *fence, char *str, int size)
546 struct pvr_fence *pvr_fence = to_pvr_fence(fence);
552 "%llu: (%s%s) refs=%u fwaddr=%#08x enqueue=%u status=%-9s %s%s",
553 (u64) pvr_fence->fence->seqno,
554 test_bit(DMA_FENCE_FLAG_ENABLE_SIGNAL_BIT,
555 &pvr_fence->fence->flags) ? "+" : "-",
556 test_bit(DMA_FENCE_FLAG_SIGNALED_BIT,
557 &pvr_fence->fence->flags) ? "+" : "-",
558 refcount_read(&pvr_fence->fence->refcount.refcount),
559 SyncCheckpointGetFirmwareAddr(
560 pvr_fence->sync_checkpoint),
561 SyncCheckpointGetEnqueuedCount(pvr_fence->sync_checkpoint),
562 SyncCheckpointGetStateString(pvr_fence->sync_checkpoint),
564 (&pvr_fence->base != pvr_fence->fence) ?
569 void pvr_fence_timeline_value_str(struct dma_fence *fence, char *str, int size)
571 struct pvr_fence *pvr_fence = to_pvr_fence(fence);
574 pvr_context_value_str(pvr_fence->fctx, str, size);
578 pvr_fence_enable_signaling(struct dma_fence *fence)
580 struct pvr_fence *pvr_fence = to_pvr_fence(fence);
586 WARN_ON_SMP(!spin_is_locked(&pvr_fence->fctx->lock));
588 if (pvr_fence_sync_is_signaled(pvr_fence, PVRSRV_FENCE_FLAG_SUPPRESS_HWP_PKT))
591 dma_fence_get(&pvr_fence->base);
593 spin_lock_irqsave(&pvr_fence->fctx->list_lock, flags);
594 list_add_tail(&pvr_fence->signal_head, &pvr_fence->fctx->signal_list);
595 spin_unlock_irqrestore(&pvr_fence->fctx->list_lock, flags);
597 PVR_FENCE_TRACE(&pvr_fence->base, "signalling enabled (%s)\n",
599 trace_pvr_fence_enable_signaling(pvr_fence);
605 pvr_fence_is_signaled(struct dma_fence *fence)
607 struct pvr_fence *pvr_fence = to_pvr_fence(fence);
610 return pvr_fence_sync_is_signaled(pvr_fence,
611 PVRSRV_FENCE_FLAG_SUPPRESS_HWP_PKT);
616 pvr_fence_release(struct dma_fence *fence)
618 struct pvr_fence *pvr_fence = to_pvr_fence(fence);
622 struct pvr_fence_context *fctx = pvr_fence->fctx;
624 PVR_FENCE_TRACE(&pvr_fence->base, "released fence (%s)\n",
626 trace_pvr_fence_release(pvr_fence);
628 spin_lock_irqsave(&fctx->list_lock, flags);
629 list_move(&pvr_fence->fence_head,
630 &fctx->deferred_free_list);
631 spin_unlock_irqrestore(&fctx->list_lock, flags);
633 kref_put(&fctx->kref, pvr_fence_context_destroy_kref);
637 const struct dma_fence_ops pvr_fence_ops = {
638 .get_driver_name = pvr_fence_get_driver_name,
639 .get_timeline_name = pvr_fence_get_timeline_name,
640 .fence_value_str = pvr_fence_fence_value_str,
641 .timeline_value_str = pvr_fence_timeline_value_str,
642 .enable_signaling = pvr_fence_enable_signaling,
643 .signaled = pvr_fence_is_signaled,
644 .wait = dma_fence_default_wait,
645 .release = pvr_fence_release,
649 * pvr_fence_create - creates a PVR fence
650 * @fctx: PVR fence context on which the PVR fence should be created
651 * @sync_checkpoint_ctx: context in which to create sync checkpoints
652 * @timeline_fd: timeline on which the PVR fence should be created
653 * @name: PVR fence name (used for debugging)
655 * Creates a PVR fence.
657 * Once the fence is finished with, pvr_fence_destroy should be called.
659 * Returns NULL if a PVR fence cannot be created.
662 pvr_fence_create(struct pvr_fence_context *fctx,
663 struct SYNC_CHECKPOINT_CONTEXT_TAG *sync_checkpoint_ctx,
664 int timeline_fd, const char *name)
666 struct pvr_fence *pvr_fence;
669 PVRSRV_ERROR srv_err;
671 if (!try_module_get(THIS_MODULE))
674 /* Note: As kmem_cache is used to allocate pvr_fence objects,
675 * make sure that all members of pvr_fence struct are initialized
678 pvr_fence = kmem_cache_alloc(pvr_fence_cache, GFP_KERNEL);
679 if (unlikely(!pvr_fence))
682 srv_err = SyncCheckpointAlloc(sync_checkpoint_ctx,
683 (PVRSRV_TIMELINE) timeline_fd, PVRSRV_NO_FENCE,
684 name, &pvr_fence->sync_checkpoint);
685 if (unlikely(srv_err != PVRSRV_OK))
688 INIT_LIST_HEAD(&pvr_fence->fence_head);
689 INIT_LIST_HEAD(&pvr_fence->signal_head);
690 pvr_fence->fctx = fctx;
691 seqno = pvr_fence_context_seqno_next(fctx);
692 /* Add the seqno to the fence name for easier debugging */
693 pvr_fence_prepare_name(pvr_fence->name, sizeof(pvr_fence->name),
696 /* Reset cb to zero */
697 memset(&pvr_fence->cb, 0, sizeof(pvr_fence->cb));
698 pvr_fence->fence = &pvr_fence->base;
700 dma_fence_init(&pvr_fence->base, &pvr_fence_ops, &fctx->lock,
701 fctx->fence_context, seqno);
703 spin_lock_irqsave(&fctx->list_lock, flags);
704 list_add_tail(&pvr_fence->fence_head, &fctx->fence_list);
705 spin_unlock_irqrestore(&fctx->list_lock, flags);
707 kref_get(&fctx->kref);
709 PVR_FENCE_TRACE(&pvr_fence->base, "created fence (%s)\n", name);
710 trace_pvr_fence_create(pvr_fence);
715 kmem_cache_free(pvr_fence_cache, pvr_fence);
717 module_put(THIS_MODULE);
723 pvr_fence_foreign_get_driver_name(struct dma_fence *fence)
725 return PVR_LDM_DRIVER_REGISTRATION_NAME;
729 pvr_fence_foreign_get_timeline_name(struct dma_fence *fence)
735 void pvr_fence_foreign_fence_value_str(struct dma_fence *fence, char *str,
738 struct pvr_fence *pvr_fence = to_pvr_fence(fence);
742 if (WARN_ON(!pvr_fence))
745 sync_addr = SyncCheckpointGetFirmwareAddr(pvr_fence->sync_checkpoint);
746 sync_value_next = PVRSRV_SYNC_CHECKPOINT_SIGNALLED;
749 * Include the fence flag bits from the foreign fence instead of our
750 * shadow copy. This is done as the shadow fence flag bits aren't used.
753 "%llu: (%s%s) refs=%u fwaddr=%#08x cur=%#08x nxt=%#08x %s",
755 test_bit(DMA_FENCE_FLAG_ENABLE_SIGNAL_BIT,
756 &pvr_fence->fence->flags) ? "+" : "-",
757 test_bit(DMA_FENCE_FLAG_SIGNALED_BIT,
758 &pvr_fence->fence->flags) ? "+" : "-",
759 refcount_read(&fence->refcount.refcount),
761 pvr_fence_sync_value(pvr_fence),
767 void pvr_fence_foreign_timeline_value_str(struct dma_fence *fence, char *str,
770 struct pvr_fence *pvr_fence = to_pvr_fence(fence);
773 pvr_context_value_str(pvr_fence->fctx, str, size);
777 pvr_fence_foreign_enable_signaling(struct dma_fence *fence)
779 WARN_ON("cannot enable signalling on foreign fence");
784 pvr_fence_foreign_wait(struct dma_fence *fence, bool intr, signed long timeout)
786 WARN_ON("cannot wait on foreign fence");
791 pvr_fence_foreign_release(struct dma_fence *fence)
793 struct pvr_fence *pvr_fence = to_pvr_fence(fence);
797 struct pvr_fence_context *fctx = pvr_fence->fctx;
798 struct dma_fence *foreign_fence = pvr_fence->fence;
800 PVR_FENCE_TRACE(&pvr_fence->base,
801 "released fence for foreign fence %llu#%d (%s)\n",
802 (u64) pvr_fence->fence->context,
803 pvr_fence->fence->seqno, pvr_fence->name);
804 trace_pvr_fence_foreign_release(pvr_fence);
806 spin_lock_irqsave(&fctx->list_lock, flags);
807 list_move(&pvr_fence->fence_head,
808 &fctx->deferred_free_list);
809 spin_unlock_irqrestore(&fctx->list_lock, flags);
811 dma_fence_put(foreign_fence);
813 kref_put(&fctx->kref,
814 pvr_fence_context_destroy_kref);
818 const struct dma_fence_ops pvr_fence_foreign_ops = {
819 .get_driver_name = pvr_fence_foreign_get_driver_name,
820 .get_timeline_name = pvr_fence_foreign_get_timeline_name,
821 .fence_value_str = pvr_fence_foreign_fence_value_str,
822 .timeline_value_str = pvr_fence_foreign_timeline_value_str,
823 .enable_signaling = pvr_fence_foreign_enable_signaling,
824 .wait = pvr_fence_foreign_wait,
825 .release = pvr_fence_foreign_release,
829 pvr_fence_foreign_signal_sync(struct dma_fence *fence, struct dma_fence_cb *cb)
831 struct pvr_fence *pvr_fence = container_of(cb, struct pvr_fence, cb);
832 struct pvr_fence_context *fctx = pvr_fence->fctx;
834 WARN_ON_ONCE(is_pvr_fence(fence));
836 /* Callback registered by dma_fence_add_callback can be called from an atomic ctx */
837 pvr_fence_sync_signal(pvr_fence, PVRSRV_FENCE_FLAG_CTX_ATOMIC);
839 trace_pvr_fence_foreign_signal(pvr_fence);
841 queue_work(fctx->fence_wq, &fctx->check_status_work);
843 PVR_FENCE_TRACE(&pvr_fence->base,
844 "foreign fence %llu#%d signalled (%s)\n",
845 (u64) pvr_fence->fence->context,
846 pvr_fence->fence->seqno, pvr_fence->name);
848 /* Drop the reference on the base fence */
849 dma_fence_put(&pvr_fence->base);
853 * pvr_fence_create_from_fence - creates a PVR fence from a fence
854 * @fctx: PVR fence context on which the PVR fence should be created
855 * @sync_checkpoint_ctx: context in which to create sync checkpoints
856 * @fence: fence from which the PVR fence should be created
857 * @fence_fd: fd for the sync file to which the fence belongs. If it doesn't
858 * belong to a sync file then PVRSRV_NO_FENCE should be given
860 * @name: PVR fence name (used for debugging)
862 * Creates a PVR fence from an existing fence. If the fence is a foreign fence,
863 * i.e. one that doesn't originate from a PVR fence context, then a new PVR
864 * fence will be created using the specified sync_checkpoint_context.
865 * Otherwise, a reference will be taken on the underlying fence and the PVR
866 * fence will be returned.
868 * Once the fence is finished with, pvr_fence_destroy should be called.
870 * Returns NULL if a PVR fence cannot be created.
874 pvr_fence_create_from_fence(struct pvr_fence_context *fctx,
875 struct SYNC_CHECKPOINT_CONTEXT_TAG *sync_checkpoint_ctx,
876 struct dma_fence *fence,
877 PVRSRV_FENCE fence_fd,
880 struct pvr_fence *pvr_fence = to_pvr_fence(fence);
883 PVRSRV_ERROR srv_err;
887 if (WARN_ON(fence->ops == &pvr_fence_foreign_ops))
889 dma_fence_get(fence);
891 PVR_FENCE_TRACE(fence, "created fence from PVR fence (%s)\n",
896 if (!try_module_get(THIS_MODULE))
899 /* Note: As kmem_cache is used to allocate pvr_fence objects,
900 * make sure that all members of pvr_fence struct are initialized
903 pvr_fence = kmem_cache_alloc(pvr_fence_cache, GFP_KERNEL);
907 srv_err = SyncCheckpointAlloc(sync_checkpoint_ctx,
908 SYNC_CHECKPOINT_FOREIGN_CHECKPOINT,
910 name, &pvr_fence->sync_checkpoint);
911 if (srv_err != PVRSRV_OK)
912 goto err_free_pvr_fence;
914 INIT_LIST_HEAD(&pvr_fence->fence_head);
915 INIT_LIST_HEAD(&pvr_fence->signal_head);
916 pvr_fence->fctx = fctx;
917 pvr_fence->fence = dma_fence_get(fence);
918 seqno = pvr_fence_context_seqno_next(fctx);
919 /* Add the seqno to the fence name for easier debugging */
920 pvr_fence_prepare_name(pvr_fence->name, sizeof(pvr_fence->name),
924 * We use the base fence to refcount the PVR fence and to do the
925 * necessary clean up once the refcount drops to 0.
927 dma_fence_init(&pvr_fence->base, &pvr_fence_foreign_ops, &fctx->lock,
928 fctx->fence_context, seqno);
931 * Take an extra reference on the base fence that gets dropped when the
932 * foreign fence is signalled.
934 dma_fence_get(&pvr_fence->base);
936 spin_lock_irqsave(&fctx->list_lock, flags);
937 list_add_tail(&pvr_fence->fence_head, &fctx->fence_list);
938 spin_unlock_irqrestore(&fctx->list_lock, flags);
939 kref_get(&fctx->kref);
941 PVR_FENCE_TRACE(&pvr_fence->base,
942 "created fence from foreign fence %llu#%d (%s)\n",
943 (u64) pvr_fence->fence->context,
944 pvr_fence->fence->seqno, name);
946 err = dma_fence_add_callback(fence, &pvr_fence->cb,
947 pvr_fence_foreign_signal_sync);
949 if (err != -ENOENT) {
950 pr_err("%s: failed to add fence callback (err=%d)",
956 * The fence has already signalled so set the sync as signalled.
957 * The "signalled" hwperf packet should be emitted because the
958 * callback won't be called for already signalled fence hence,
959 * PVRSRV_FENCE_FLAG_NONE flag.
961 pvr_fence_sync_signal(pvr_fence, PVRSRV_FENCE_FLAG_NONE);
962 PVR_FENCE_TRACE(&pvr_fence->base,
963 "foreign fence %llu#%d already signaled (%s)\n",
964 (u64) pvr_fence->fence->context,
965 pvr_fence->fence->seqno,
967 dma_fence_put(&pvr_fence->base);
970 trace_pvr_fence_foreign_create(pvr_fence);
975 kref_put(&fctx->kref, pvr_fence_context_destroy_kref);
976 spin_lock_irqsave(&fctx->list_lock, flags);
977 list_del(&pvr_fence->fence_head);
978 spin_unlock_irqrestore(&fctx->list_lock, flags);
979 SyncCheckpointFree(pvr_fence->sync_checkpoint);
981 kmem_cache_free(pvr_fence_cache, pvr_fence);
983 module_put(THIS_MODULE);
989 * pvr_fence_destroy - destroys a PVR fence
990 * @pvr_fence: PVR fence to destroy
992 * Destroys a PVR fence. Upon return, the PVR fence may still exist if something
993 * else still references the underlying fence, e.g. a reservation object, or if
994 * software signalling has been enabled and the fence hasn't yet been signalled.
997 pvr_fence_destroy(struct pvr_fence *pvr_fence)
999 PVR_FENCE_TRACE(&pvr_fence->base, "destroyed fence (%s)\n",
1002 dma_fence_put(&pvr_fence->base);
1006 * pvr_fence_sw_signal - signals a PVR fence sync
1007 * @pvr_fence: PVR fence to signal
1009 * Sets the PVR fence sync value to signalled.
1011 * Returns -EINVAL if the PVR fence represents a foreign fence.
1014 pvr_fence_sw_signal(struct pvr_fence *pvr_fence)
1016 if (!is_our_fence(pvr_fence->fctx, &pvr_fence->base))
1019 pvr_fence_sync_signal(pvr_fence, PVRSRV_FENCE_FLAG_NONE);
1021 queue_work(pvr_fence->fctx->fence_wq,
1022 &pvr_fence->fctx->check_status_work);
1024 PVR_FENCE_TRACE(&pvr_fence->base, "sw set fence sync signalled (%s)\n",
1031 * pvr_fence_sw_error - errors the sync checkpoint backing a PVR fence
1032 * @pvr_fence: PVR fence to error
1034 * Sets the PVR fence sync checkpoint value to errored.
1036 * Returns -EINVAL if the PVR fence represents a foreign fence.
1039 pvr_fence_sw_error(struct pvr_fence *pvr_fence)
1041 if (!is_our_fence(pvr_fence->fctx, &pvr_fence->base))
1044 SyncCheckpointError(pvr_fence->sync_checkpoint, PVRSRV_FENCE_FLAG_NONE);
1045 PVR_FENCE_TRACE(&pvr_fence->base, "sw set fence sync errored (%s)\n",
1052 pvr_fence_get_checkpoints(struct pvr_fence **pvr_fences, u32 nr_fences,
1053 struct SYNC_CHECKPOINT_TAG **fence_checkpoints)
1055 struct SYNC_CHECKPOINT_TAG **next_fence_checkpoint = fence_checkpoints;
1056 struct pvr_fence **next_pvr_fence = pvr_fences;
1057 int fence_checkpoint_idx;
1059 if (nr_fences > 0) {
1061 for (fence_checkpoint_idx = 0; fence_checkpoint_idx < nr_fences;
1062 fence_checkpoint_idx++) {
1063 struct pvr_fence *next_fence = *next_pvr_fence++;
1064 *next_fence_checkpoint++ = next_fence->sync_checkpoint;
1065 /* Take reference on sync checkpoint (will be dropped
1066 * later by kick code)
1068 SyncCheckpointTakeRef(next_fence->sync_checkpoint);
1075 struct SYNC_CHECKPOINT_TAG *
1076 pvr_fence_get_checkpoint(struct pvr_fence *update_fence)
1078 return update_fence->sync_checkpoint;
1082 * pvr_fence_dump_info_on_stalled_ufos - displays debug
1083 * information on a native fence associated with any of
1084 * the ufos provided. This function will be called from
1085 * pvr_sync_file.c if the driver determines any GPU work
1086 * is stuck waiting for a sync checkpoint representing a
1087 * foreign sync to be signalled.
1088 * @nr_ufos: number of ufos in vaddrs
1089 * @vaddrs: array of FW addresses of UFOs which the
1090 * driver is waiting on.
1092 * Output debug information to kernel log on linux fences
1093 * which would be responsible for signalling the sync
1094 * checkpoints indicated by the ufo vaddresses.
1096 * Returns the number of ufos in the array which were found
1097 * to be associated with foreign syncs.
1099 u32 pvr_fence_dump_info_on_stalled_ufos(struct pvr_fence_context *fctx,
1100 u32 nr_ufos, u32 *vaddrs)
1103 struct pvr_fence *pvr_fence;
1104 unsigned long flags;
1106 spin_lock_irqsave(&fctx->list_lock, flags);
1107 /* dump info on any ufos in our active list */
1108 list_for_each_entry(pvr_fence, &fctx->fence_list, fence_head) {
1109 u32 *this_ufo_vaddr = vaddrs;
1111 DUMPDEBUG_PRINTF_FUNC *pfnDummy = NULL;
1113 for (ufo_num = 0; ufo_num < nr_ufos; ufo_num++) {
1114 struct SYNC_CHECKPOINT_TAG *checkpoint =
1115 pvr_fence->sync_checkpoint;
1116 const u32 fence_ufo_addr =
1117 SyncCheckpointGetFirmwareAddr(checkpoint);
1119 if (fence_ufo_addr != this_ufo_vaddr[ufo_num])
1122 /* Dump sync info */
1123 PVR_DUMPDEBUG_LOG(pfnDummy, NULL,
1124 "\tSyncID = %d, FWAddr = 0x%08x: TLID = %d (Foreign Fence - [%p] %s)",
1125 SyncCheckpointGetId(checkpoint),
1127 SyncCheckpointGetTimeline(checkpoint),
1133 spin_unlock_irqrestore(&fctx->list_lock, flags);