aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/pvr/services4/srvkm/env/linux/pvr_sw_fence.c')
-rw-r--r--drivers/gpu/pvr/services4/srvkm/env/linux/pvr_sw_fence.c141
1 files changed, 141 insertions, 0 deletions
diff --git a/drivers/gpu/pvr/services4/srvkm/env/linux/pvr_sw_fence.c b/drivers/gpu/pvr/services4/srvkm/env/linux/pvr_sw_fence.c
new file mode 100644
index 000000000000..7c3006d711f2
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/env/linux/pvr_sw_fence.c
@@ -0,0 +1,141 @@
1/* -*- mode: c; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
2/* vi: set ts=8 sw=8 sts=8: */
3/*************************************************************************/ /*!
4@File
5@Codingstyle LinuxKernel
6@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
7@License Strictly Confidential.
8*/ /**************************************************************************/
9
10#include <linux/kernel.h>
11#include <linux/spinlock_types.h>
12#include <linux/atomic.h>
13#include <linux/slab.h>
14#include <linux/printk.h>
15#include <linux/bug.h>
16#include <linux/sync_file.h>
17
18#include "img_types.h"
19#include "services_headers.h"
20#include "servicesext.h"
21#include "pvr_sw_fence.h"
22
23struct PVR_SW_FENCE_CONTEXT
24{
25 struct kref sRef;
26 IMG_INT32 i32ContextId;
27 const char *psCtxName;
28 const char *psDriverName;
29 atomic_t sSeqno;
30 atomic_t sFenceCnt;
31};
32
33struct PVR_SW_FENCE
34{
35 struct dma_fence sBase;
36 struct PVR_SW_FENCE_CONTEXT *psSWFenceCtx;
37 spinlock_t sLock;
38};
39
40#define to_pvr_sw_fence(fence) container_of(fence, struct PVR_SW_FENCE, sBase)
41
42static inline unsigned
43pvr_sw_fence_context_seqno_next(struct PVR_SW_FENCE_CONTEXT *psSWFenceCtx)
44{
45 return atomic_inc_return(&psSWFenceCtx->sSeqno) - 1;
46}
47
48static const char * pvr_sw_fence_get_driver_name(struct dma_fence *psFence)
49{
50 struct PVR_SW_FENCE *psPVRSwFence = to_pvr_sw_fence(psFence);
51
52 return psPVRSwFence->psSWFenceCtx->psDriverName;
53}
54
55static const char * pvr_sw_fence_get_timeline_name(struct dma_fence *psFence)
56{
57 struct PVR_SW_FENCE *psPVRSwFence = to_pvr_sw_fence(psFence);
58
59 return psPVRSwFence->psSWFenceCtx->psCtxName;
60}
61
62static bool pvr_sw_fence_enable_signaling(struct dma_fence *psFence)
63{
64 return true;
65}
66
67static void pvr_sw_fence_context_destroy_kref(struct kref *kref)
68{
69 struct PVR_SW_FENCE_CONTEXT *psPVRSwFence = container_of(kref, struct PVR_SW_FENCE_CONTEXT, sRef);
70 unsigned fence_count;
71
72 fence_count = atomic_read(&psPVRSwFence->sFenceCnt);
73 if (WARN_ON(fence_count))
74 pr_debug("%s context has %u fence(s) remaining\n", psPVRSwFence->psCtxName, fence_count);
75
76 kfree(psPVRSwFence);
77}
78
79static void pvr_sw_fence_release(struct dma_fence *psFence)
80{
81 struct PVR_SW_FENCE *psPVRSwFence = to_pvr_sw_fence(psFence);
82
83 atomic_dec(&psPVRSwFence->psSWFenceCtx->sFenceCnt);
84 kref_put(&psPVRSwFence->psSWFenceCtx->sRef,
85 pvr_sw_fence_context_destroy_kref);
86 kfree(psPVRSwFence);
87}
88
89static struct dma_fence_ops pvr_sw_fence_ops = {
90 .get_driver_name = pvr_sw_fence_get_driver_name,
91 .get_timeline_name = pvr_sw_fence_get_timeline_name,
92 .enable_signaling = pvr_sw_fence_enable_signaling,
93 .wait = dma_fence_default_wait,
94 .release = pvr_sw_fence_release,
95};
96
97struct PVR_SW_FENCE_CONTEXT *
98pvr_sw_fence_context_create(const char *context_name, const char *driver_name)
99{
100 struct PVR_SW_FENCE_CONTEXT *psSWFenceCtx;
101
102 psSWFenceCtx = kmalloc(sizeof(*psSWFenceCtx), GFP_KERNEL);
103 if (!psSWFenceCtx)
104 return NULL;
105
106 psSWFenceCtx->i32ContextId = dma_fence_context_alloc(1);
107 psSWFenceCtx->psCtxName = context_name;
108 psSWFenceCtx->psDriverName = driver_name;
109 atomic_set(&psSWFenceCtx->sSeqno, 0);
110 atomic_set(&psSWFenceCtx->sFenceCnt, 0);
111 kref_init(&psSWFenceCtx->sRef);
112
113 return psSWFenceCtx;
114}
115
116void pvr_sw_fence_context_destroy(struct PVR_SW_FENCE_CONTEXT *psSWFenceCtx)
117{
118 kref_put(&psSWFenceCtx->sRef, pvr_sw_fence_context_destroy_kref);
119}
120
121struct dma_fence *
122pvr_sw_fence_create(struct PVR_SW_FENCE_CONTEXT *psSWFenceCtx)
123{
124 struct PVR_SW_FENCE *psPVRSwFence;
125 unsigned int seqno;
126
127 psPVRSwFence = kmalloc(sizeof(*psPVRSwFence), GFP_KERNEL);
128 if (!psPVRSwFence)
129 return NULL;
130
131 spin_lock_init(&psPVRSwFence->sLock);
132 psPVRSwFence->psSWFenceCtx = psSWFenceCtx;
133
134 seqno = pvr_sw_fence_context_seqno_next(psSWFenceCtx);
135 dma_fence_init(&psPVRSwFence->sBase, &pvr_sw_fence_ops, &psPVRSwFence->sLock, psSWFenceCtx->i32ContextId, seqno);
136
137 atomic_inc(&psSWFenceCtx->sFenceCnt);
138 kref_get(&psSWFenceCtx->sRef);
139
140 return &psPVRSwFence->sBase;
141}