1 /**************************************************************************
3 * Copyright (c) 2006-2008 Tungsten Graphics, Inc., Cedar Park, TX., USA
5 * Copyright (c) 2009 VMware, Inc., Palo Alto, CA., USA
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms and conditions of the GNU General Public License,
10 * version 2, as published by the Free Software Foundation.
12 * This program is distributed in the hope it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
17 * You should have received a copy of the GNU General Public License along with
18 * this program; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
21 **************************************************************************/
23 * Authors: Thomas Hellstrom <thomas-at-tungstengraphics-dot-com>
27 #include "psb_ttm_fence_user.h"
28 #include "ttm/ttm_object.h"
29 #include "psb_ttm_fence_driver.h"
30 #include "psb_ttm_userobj_api.h"
33 * struct ttm_fence_user_object
35 * @base: The base object used for user-space visibility and refcounting.
37 * @fence: The fence object itself.
41 struct ttm_fence_user_object
{
42 struct ttm_base_object base
;
43 struct ttm_fence_object fence
;
46 static struct ttm_fence_user_object
*ttm_fence_user_object_lookup(
47 struct ttm_object_file
*tfile
,
50 struct ttm_base_object
*base
;
52 base
= ttm_base_object_lookup(tfile
, handle
);
53 if (unlikely(base
== NULL
)) {
54 printk(KERN_ERR
"Invalid fence handle 0x%08lx\n",
55 (unsigned long)handle
);
59 if (unlikely(base
->object_type
!= ttm_fence_type
)) {
60 ttm_base_object_unref(&base
);
61 printk(KERN_ERR
"Invalid fence handle 0x%08lx\n",
62 (unsigned long)handle
);
66 return container_of(base
, struct ttm_fence_user_object
, base
);
70 * The fence object destructor.
73 static void ttm_fence_user_destroy(struct ttm_fence_object
*fence
)
75 struct ttm_fence_user_object
*ufence
=
76 container_of(fence
, struct ttm_fence_user_object
, fence
);
78 ttm_mem_global_free(fence
->fdev
->mem_glob
, sizeof(*ufence
));
83 * The base object destructor. We basically unly unreference the
84 * attached fence object.
87 static void ttm_fence_user_release(struct ttm_base_object
**p_base
)
89 struct ttm_fence_user_object
*ufence
;
90 struct ttm_base_object
*base
= *p_base
;
91 struct ttm_fence_object
*fence
;
95 if (unlikely(base
== NULL
))
98 ufence
= container_of(base
, struct ttm_fence_user_object
, base
);
99 fence
= &ufence
->fence
;
100 ttm_fence_object_unref(&fence
);
104 ttm_fence_user_create(struct ttm_fence_device
*fdev
,
105 struct ttm_object_file
*tfile
,
106 uint32_t fence_class
,
107 uint32_t fence_types
,
108 uint32_t create_flags
,
109 struct ttm_fence_object
**fence
,
110 uint32_t *user_handle
)
113 struct ttm_fence_object
*tmp
;
114 struct ttm_fence_user_object
*ufence
;
116 ret
= ttm_mem_global_alloc(fdev
->mem_glob
,
120 if (unlikely(ret
!= 0))
123 ufence
= kmalloc(sizeof(*ufence
), GFP_KERNEL
);
124 if (unlikely(ufence
== NULL
)) {
125 ttm_mem_global_free(fdev
->mem_glob
, sizeof(*ufence
));
129 ret
= ttm_fence_object_init(fdev
,
131 fence_types
, create_flags
,
132 &ttm_fence_user_destroy
, &ufence
->fence
);
134 if (unlikely(ret
!= 0))
138 * One fence ref is held by the fence ptr we return.
139 * The other one by the base object. Need to up the
140 * fence refcount before we publish this object to
144 tmp
= ttm_fence_object_ref(&ufence
->fence
);
145 ret
= ttm_base_object_init(tfile
, &ufence
->base
,
146 false, ttm_fence_type
,
147 &ttm_fence_user_release
, NULL
);
149 if (unlikely(ret
!= 0))
152 *fence
= &ufence
->fence
;
153 *user_handle
= ufence
->base
.hash
.key
;
157 ttm_fence_object_unref(&tmp
);
158 tmp
= &ufence
->fence
;
159 ttm_fence_object_unref(&tmp
);
162 ttm_mem_global_free(fdev
->mem_glob
, sizeof(*ufence
));
167 int ttm_fence_signaled_ioctl(struct ttm_object_file
*tfile
, void *data
)
170 union ttm_fence_signaled_arg
*arg
= data
;
171 struct ttm_fence_object
*fence
;
172 struct ttm_fence_info info
;
173 struct ttm_fence_user_object
*ufence
;
174 struct ttm_base_object
*base
;
177 ufence
= ttm_fence_user_object_lookup(tfile
, arg
->req
.handle
);
178 if (unlikely(ufence
== NULL
))
181 fence
= &ufence
->fence
;
183 if (arg
->req
.flush
) {
184 ret
= ttm_fence_object_flush(fence
, arg
->req
.fence_type
);
185 if (unlikely(ret
!= 0))
189 info
= ttm_fence_get_info(fence
);
190 arg
->rep
.signaled_types
= info
.signaled_types
;
191 arg
->rep
.fence_error
= info
.error
;
194 base
= &ufence
->base
;
195 ttm_base_object_unref(&base
);
199 int ttm_fence_finish_ioctl(struct ttm_object_file
*tfile
, void *data
)
202 union ttm_fence_finish_arg
*arg
= data
;
203 struct ttm_fence_user_object
*ufence
;
204 struct ttm_base_object
*base
;
205 struct ttm_fence_object
*fence
;
208 ufence
= ttm_fence_user_object_lookup(tfile
, arg
->req
.handle
);
209 if (unlikely(ufence
== NULL
))
212 fence
= &ufence
->fence
;
214 ret
= ttm_fence_object_wait(fence
,
215 arg
->req
.mode
& TTM_FENCE_FINISH_MODE_LAZY
,
216 true, arg
->req
.fence_type
);
217 if (likely(ret
== 0)) {
218 struct ttm_fence_info info
= ttm_fence_get_info(fence
);
220 arg
->rep
.signaled_types
= info
.signaled_types
;
221 arg
->rep
.fence_error
= info
.error
;
224 base
= &ufence
->base
;
225 ttm_base_object_unref(&base
);
230 int ttm_fence_unref_ioctl(struct ttm_object_file
*tfile
, void *data
)
232 struct ttm_fence_unref_arg
*arg
= data
;
235 ret
= ttm_ref_object_base_unref(tfile
, arg
->handle
, ttm_fence_type
);