Rev 5078 | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 5078 | Rev 6296 | ||
---|---|---|---|
1 | /************************************************************************** |
1 | /************************************************************************** |
2 | * |
2 | * |
3 | * Copyright © 2009-2012 VMware, Inc., Palo Alto, CA., USA |
3 | * Copyright © 2009-2015 VMware, Inc., Palo Alto, CA., USA |
4 | * All Rights Reserved. |
4 | * All Rights Reserved. |
5 | * |
5 | * |
6 | * Permission is hereby granted, free of charge, to any person obtaining a |
6 | * Permission is hereby granted, free of charge, to any person obtaining a |
7 | * copy of this software and associated documentation files (the |
7 | * copy of this software and associated documentation files (the |
8 | * "Software"), to deal in the Software without restriction, including |
8 | * "Software"), to deal in the Software without restriction, including |
9 | * without limitation the rights to use, copy, modify, merge, publish, |
9 | * without limitation the rights to use, copy, modify, merge, publish, |
10 | * distribute, sub license, and/or sell copies of the Software, and to |
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 |
11 | * permit persons to whom the Software is furnished to do so, subject to |
12 | * the following conditions: |
12 | * the following conditions: |
13 | * |
13 | * |
14 | * The above copyright notice and this permission notice (including the |
14 | * The above copyright notice and this permission notice (including the |
15 | * next paragraph) shall be included in all copies or substantial portions |
15 | * next paragraph) shall be included in all copies or substantial portions |
16 | * of the Software. |
16 | * of the Software. |
17 | * |
17 | * |
18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
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, |
19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
20 | * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL |
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, |
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 |
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 |
23 | * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE |
24 | * USE OR OTHER DEALINGS IN THE SOFTWARE. |
24 | * USE OR OTHER DEALINGS IN THE SOFTWARE. |
25 | * |
25 | * |
26 | **************************************************************************/ |
26 | **************************************************************************/ |
27 | 27 | ||
28 | #include "vmwgfx_drv.h" |
28 | #include "vmwgfx_drv.h" |
29 | #include "vmwgfx_resource_priv.h" |
29 | #include "vmwgfx_resource_priv.h" |
- | 30 | #include "vmwgfx_binding.h" |
|
30 | #include "ttm/ttm_placement.h" |
31 | #include "ttm/ttm_placement.h" |
31 | 32 | ||
32 | #define VMW_COMPAT_SHADER_HT_ORDER 12 |
33 | #define VMW_COMPAT_SHADER_HT_ORDER 12 |
33 | 34 | ||
34 | #if 0 |
35 | #if 0 |
35 | struct vmw_shader { |
36 | struct vmw_shader { |
36 | struct vmw_resource res; |
37 | struct vmw_resource res; |
37 | SVGA3dShaderType type; |
38 | SVGA3dShaderType type; |
38 | uint32_t size; |
39 | uint32_t size; |
- | 40 | uint8_t num_input_sig; |
|
- | 41 | uint8_t num_output_sig; |
|
39 | }; |
42 | }; |
40 | 43 | ||
41 | struct vmw_user_shader { |
44 | struct vmw_user_shader { |
42 | struct ttm_base_object base; |
45 | struct ttm_base_object base; |
43 | struct vmw_shader shader; |
46 | struct vmw_shader shader; |
44 | }; |
47 | }; |
45 | - | ||
46 | /** |
- | |
47 | * enum vmw_compat_shader_state - Staging state for compat shaders |
- | |
48 | */ |
48 | |
49 | enum vmw_compat_shader_state { |
- | |
50 | VMW_COMPAT_COMMITED, |
- | |
51 | VMW_COMPAT_ADD, |
- | |
52 | VMW_COMPAT_DEL |
- | |
53 | }; |
- | |
54 | - | ||
55 | /** |
49 | struct vmw_dx_shader { |
56 | * struct vmw_compat_shader - Metadata for compat shaders. |
- | |
57 | * |
- | |
58 | * @handle: The TTM handle of the guest backed shader. |
- | |
59 | * @tfile: The struct ttm_object_file the guest backed shader is registered |
- | |
60 | * with. |
- | |
61 | * @hash: Hash item for lookup. |
- | |
62 | * @head: List head for staging lists or the compat shader manager list. |
50 | struct vmw_resource res; |
63 | * @state: Staging state. |
- | |
64 | * |
- | |
65 | * The structure is protected by the cmdbuf lock. |
- | |
66 | */ |
51 | struct vmw_resource *ctx; |
67 | struct vmw_compat_shader { |
52 | struct vmw_resource *cotable; |
68 | u32 handle; |
- | |
69 | struct ttm_object_file *tfile; |
53 | u32 id; |
70 | struct drm_hash_item hash; |
54 | bool committed; |
71 | struct list_head head; |
- | |
72 | enum vmw_compat_shader_state state; |
55 | struct list_head cotable_head; |
73 | }; |
- | |
74 | - | ||
75 | /** |
- | |
76 | * struct vmw_compat_shader_manager - Compat shader manager. |
- | |
77 | * |
- | |
78 | * @shaders: Hash table containing staged and commited compat shaders |
- | |
79 | * @list: List of commited shaders. |
- | |
80 | * @dev_priv: Pointer to a device private structure. |
- | |
81 | * |
- | |
82 | * @shaders and @list are protected by the cmdbuf mutex for now. |
56 | }; |
83 | */ |
57 | |
84 | struct vmw_compat_shader_manager { |
- | |
85 | struct drm_open_hash shaders; |
58 | static uint64_t vmw_user_shader_size; |
86 | struct list_head list; |
- | |
87 | struct vmw_private *dev_priv; |
59 | static uint64_t vmw_shader_size; |
88 | }; |
60 | static size_t vmw_shader_dx_size; |
89 | 61 | ||
90 | static void vmw_user_shader_free(struct vmw_resource *res); |
62 | static void vmw_user_shader_free(struct vmw_resource *res); |
91 | static struct vmw_resource * |
63 | static struct vmw_resource * |
92 | vmw_user_shader_base_to_res(struct ttm_base_object *base); |
64 | vmw_user_shader_base_to_res(struct ttm_base_object *base); |
93 | 65 | ||
94 | static int vmw_gb_shader_create(struct vmw_resource *res); |
66 | static int vmw_gb_shader_create(struct vmw_resource *res); |
95 | static int vmw_gb_shader_bind(struct vmw_resource *res, |
67 | static int vmw_gb_shader_bind(struct vmw_resource *res, |
96 | struct ttm_validate_buffer *val_buf); |
68 | struct ttm_validate_buffer *val_buf); |
97 | static int vmw_gb_shader_unbind(struct vmw_resource *res, |
69 | static int vmw_gb_shader_unbind(struct vmw_resource *res, |
98 | bool readback, |
70 | bool readback, |
99 | struct ttm_validate_buffer *val_buf); |
71 | struct ttm_validate_buffer *val_buf); |
100 | static int vmw_gb_shader_destroy(struct vmw_resource *res); |
72 | static int vmw_gb_shader_destroy(struct vmw_resource *res); |
- | 73 | ||
- | 74 | static int vmw_dx_shader_create(struct vmw_resource *res); |
|
- | 75 | static int vmw_dx_shader_bind(struct vmw_resource *res, |
|
- | 76 | struct ttm_validate_buffer *val_buf); |
|
- | 77 | static int vmw_dx_shader_unbind(struct vmw_resource *res, |
|
- | 78 | bool readback, |
|
- | 79 | struct ttm_validate_buffer *val_buf); |
|
- | 80 | static void vmw_dx_shader_commit_notify(struct vmw_resource *res, |
|
- | 81 | enum vmw_cmdbuf_res_state state); |
|
- | 82 | static bool vmw_shader_id_ok(u32 user_key, SVGA3dShaderType shader_type); |
|
- | 83 | static u32 vmw_shader_key(u32 user_key, SVGA3dShaderType shader_type); |
|
- | 84 | static uint64_t vmw_user_shader_size; |
|
101 | 85 | ||
102 | static const struct vmw_user_resource_conv user_shader_conv = { |
86 | static const struct vmw_user_resource_conv user_shader_conv = { |
103 | .object_type = VMW_RES_SHADER, |
87 | .object_type = VMW_RES_SHADER, |
104 | .base_obj_to_res = vmw_user_shader_base_to_res, |
88 | .base_obj_to_res = vmw_user_shader_base_to_res, |
105 | .res_free = vmw_user_shader_free |
89 | .res_free = vmw_user_shader_free |
106 | }; |
90 | }; |
107 | 91 | ||
108 | const struct vmw_user_resource_conv *user_shader_converter = |
92 | const struct vmw_user_resource_conv *user_shader_converter = |
109 | &user_shader_conv; |
93 | &user_shader_conv; |
110 | 94 | ||
111 | 95 | ||
112 | static const struct vmw_res_func vmw_gb_shader_func = { |
96 | static const struct vmw_res_func vmw_gb_shader_func = { |
113 | .res_type = vmw_res_shader, |
97 | .res_type = vmw_res_shader, |
114 | .needs_backup = true, |
98 | .needs_backup = true, |
115 | .may_evict = true, |
99 | .may_evict = true, |
116 | .type_name = "guest backed shaders", |
100 | .type_name = "guest backed shaders", |
117 | .backup_placement = &vmw_mob_placement, |
101 | .backup_placement = &vmw_mob_placement, |
118 | .create = vmw_gb_shader_create, |
102 | .create = vmw_gb_shader_create, |
119 | .destroy = vmw_gb_shader_destroy, |
103 | .destroy = vmw_gb_shader_destroy, |
120 | .bind = vmw_gb_shader_bind, |
104 | .bind = vmw_gb_shader_bind, |
121 | .unbind = vmw_gb_shader_unbind |
105 | .unbind = vmw_gb_shader_unbind |
122 | }; |
106 | }; |
- | 107 | ||
- | 108 | static const struct vmw_res_func vmw_dx_shader_func = { |
|
- | 109 | .res_type = vmw_res_shader, |
|
- | 110 | .needs_backup = true, |
|
- | 111 | .may_evict = false, |
|
- | 112 | .type_name = "dx shaders", |
|
- | 113 | .backup_placement = &vmw_mob_placement, |
|
- | 114 | .create = vmw_dx_shader_create, |
|
- | 115 | /* |
|
- | 116 | * The destroy callback is only called with a committed resource on |
|
- | 117 | * context destroy, in which case we destroy the cotable anyway, |
|
- | 118 | * so there's no need to destroy DX shaders separately. |
|
- | 119 | */ |
|
- | 120 | .destroy = NULL, |
|
- | 121 | .bind = vmw_dx_shader_bind, |
|
- | 122 | .unbind = vmw_dx_shader_unbind, |
|
- | 123 | .commit_notify = vmw_dx_shader_commit_notify, |
|
- | 124 | }; |
|
123 | 125 | ||
124 | /** |
126 | /** |
125 | * Shader management: |
127 | * Shader management: |
126 | */ |
128 | */ |
127 | 129 | ||
128 | static inline struct vmw_shader * |
130 | static inline struct vmw_shader * |
129 | vmw_res_to_shader(struct vmw_resource *res) |
131 | vmw_res_to_shader(struct vmw_resource *res) |
130 | { |
132 | { |
131 | return container_of(res, struct vmw_shader, res); |
133 | return container_of(res, struct vmw_shader, res); |
132 | } |
134 | } |
- | 135 | ||
- | 136 | /** |
|
- | 137 | * vmw_res_to_dx_shader - typecast a struct vmw_resource to a |
|
- | 138 | * struct vmw_dx_shader |
|
- | 139 | * |
|
- | 140 | * @res: Pointer to the struct vmw_resource. |
|
- | 141 | */ |
|
- | 142 | static inline struct vmw_dx_shader * |
|
- | 143 | vmw_res_to_dx_shader(struct vmw_resource *res) |
|
- | 144 | { |
|
- | 145 | return container_of(res, struct vmw_dx_shader, res); |
|
- | 146 | } |
|
133 | 147 | ||
134 | static void vmw_hw_shader_destroy(struct vmw_resource *res) |
148 | static void vmw_hw_shader_destroy(struct vmw_resource *res) |
- | 149 | { |
|
135 | { |
150 | if (likely(res->func->destroy)) |
- | 151 | (void) res->func->destroy(res); |
|
- | 152 | else |
|
136 | (void) vmw_gb_shader_destroy(res); |
153 | res->id = -1; |
- | 154 | } |
|
137 | } |
155 | |
138 | 156 | ||
139 | static int vmw_gb_shader_init(struct vmw_private *dev_priv, |
157 | static int vmw_gb_shader_init(struct vmw_private *dev_priv, |
140 | struct vmw_resource *res, |
158 | struct vmw_resource *res, |
141 | uint32_t size, |
159 | uint32_t size, |
142 | uint64_t offset, |
160 | uint64_t offset, |
143 | SVGA3dShaderType type, |
161 | SVGA3dShaderType type, |
- | 162 | uint8_t num_input_sig, |
|
- | 163 | uint8_t num_output_sig, |
|
144 | struct vmw_dma_buffer *byte_code, |
164 | struct vmw_dma_buffer *byte_code, |
145 | void (*res_free) (struct vmw_resource *res)) |
165 | void (*res_free) (struct vmw_resource *res)) |
146 | { |
166 | { |
147 | struct vmw_shader *shader = vmw_res_to_shader(res); |
167 | struct vmw_shader *shader = vmw_res_to_shader(res); |
148 | int ret; |
168 | int ret; |
149 | 169 | ||
150 | ret = vmw_resource_init(dev_priv, res, true, |
170 | ret = vmw_resource_init(dev_priv, res, true, res_free, |
151 | res_free, &vmw_gb_shader_func); |
- | |
152 | 171 | &vmw_gb_shader_func); |
|
153 | 172 | ||
154 | if (unlikely(ret != 0)) { |
173 | if (unlikely(ret != 0)) { |
155 | if (res_free) |
174 | if (res_free) |
156 | res_free(res); |
175 | res_free(res); |
157 | else |
176 | else |
158 | kfree(res); |
177 | kfree(res); |
159 | return ret; |
178 | return ret; |
160 | } |
179 | } |
161 | 180 | ||
162 | res->backup_size = size; |
181 | res->backup_size = size; |
163 | if (byte_code) { |
182 | if (byte_code) { |
164 | res->backup = vmw_dmabuf_reference(byte_code); |
183 | res->backup = vmw_dmabuf_reference(byte_code); |
165 | res->backup_offset = offset; |
184 | res->backup_offset = offset; |
166 | } |
185 | } |
167 | shader->size = size; |
186 | shader->size = size; |
168 | shader->type = type; |
187 | shader->type = type; |
- | 188 | shader->num_input_sig = num_input_sig; |
|
- | 189 | shader->num_output_sig = num_output_sig; |
|
169 | 190 | ||
170 | vmw_resource_activate(res, vmw_hw_shader_destroy); |
191 | vmw_resource_activate(res, vmw_hw_shader_destroy); |
171 | return 0; |
192 | return 0; |
172 | } |
193 | } |
- | 194 | ||
- | 195 | /* |
|
- | 196 | * GB shader code: |
|
- | 197 | */ |
|
173 | 198 | ||
174 | static int vmw_gb_shader_create(struct vmw_resource *res) |
199 | static int vmw_gb_shader_create(struct vmw_resource *res) |
175 | { |
200 | { |
176 | struct vmw_private *dev_priv = res->dev_priv; |
201 | struct vmw_private *dev_priv = res->dev_priv; |
177 | struct vmw_shader *shader = vmw_res_to_shader(res); |
202 | struct vmw_shader *shader = vmw_res_to_shader(res); |
178 | int ret; |
203 | int ret; |
179 | struct { |
204 | struct { |
180 | SVGA3dCmdHeader header; |
205 | SVGA3dCmdHeader header; |
181 | SVGA3dCmdDefineGBShader body; |
206 | SVGA3dCmdDefineGBShader body; |
182 | } *cmd; |
207 | } *cmd; |
183 | 208 | ||
184 | if (likely(res->id != -1)) |
209 | if (likely(res->id != -1)) |
185 | return 0; |
210 | return 0; |
186 | 211 | ||
187 | ret = vmw_resource_alloc_id(res); |
212 | ret = vmw_resource_alloc_id(res); |
188 | if (unlikely(ret != 0)) { |
213 | if (unlikely(ret != 0)) { |
189 | DRM_ERROR("Failed to allocate a shader id.\n"); |
214 | DRM_ERROR("Failed to allocate a shader id.\n"); |
190 | goto out_no_id; |
215 | goto out_no_id; |
191 | } |
216 | } |
192 | 217 | ||
193 | if (unlikely(res->id >= VMWGFX_NUM_GB_SHADER)) { |
218 | if (unlikely(res->id >= VMWGFX_NUM_GB_SHADER)) { |
194 | ret = -EBUSY; |
219 | ret = -EBUSY; |
195 | goto out_no_fifo; |
220 | goto out_no_fifo; |
196 | } |
221 | } |
197 | 222 | ||
198 | cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd)); |
223 | cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd)); |
199 | if (unlikely(cmd == NULL)) { |
224 | if (unlikely(cmd == NULL)) { |
200 | DRM_ERROR("Failed reserving FIFO space for shader " |
225 | DRM_ERROR("Failed reserving FIFO space for shader " |
201 | "creation.\n"); |
226 | "creation.\n"); |
202 | ret = -ENOMEM; |
227 | ret = -ENOMEM; |
203 | goto out_no_fifo; |
228 | goto out_no_fifo; |
204 | } |
229 | } |
205 | 230 | ||
206 | cmd->header.id = SVGA_3D_CMD_DEFINE_GB_SHADER; |
231 | cmd->header.id = SVGA_3D_CMD_DEFINE_GB_SHADER; |
207 | cmd->header.size = sizeof(cmd->body); |
232 | cmd->header.size = sizeof(cmd->body); |
208 | cmd->body.shid = res->id; |
233 | cmd->body.shid = res->id; |
209 | cmd->body.type = shader->type; |
234 | cmd->body.type = shader->type; |
210 | cmd->body.sizeInBytes = shader->size; |
235 | cmd->body.sizeInBytes = shader->size; |
211 | vmw_fifo_commit(dev_priv, sizeof(*cmd)); |
236 | vmw_fifo_commit(dev_priv, sizeof(*cmd)); |
212 | (void) vmw_3d_resource_inc(dev_priv, false); |
237 | vmw_fifo_resource_inc(dev_priv); |
213 | 238 | ||
214 | return 0; |
239 | return 0; |
215 | 240 | ||
216 | out_no_fifo: |
241 | out_no_fifo: |
217 | vmw_resource_release_id(res); |
242 | vmw_resource_release_id(res); |
218 | out_no_id: |
243 | out_no_id: |
219 | return ret; |
244 | return ret; |
220 | } |
245 | } |
221 | 246 | ||
222 | static int vmw_gb_shader_bind(struct vmw_resource *res, |
247 | static int vmw_gb_shader_bind(struct vmw_resource *res, |
223 | struct ttm_validate_buffer *val_buf) |
248 | struct ttm_validate_buffer *val_buf) |
224 | { |
249 | { |
225 | struct vmw_private *dev_priv = res->dev_priv; |
250 | struct vmw_private *dev_priv = res->dev_priv; |
226 | struct { |
251 | struct { |
227 | SVGA3dCmdHeader header; |
252 | SVGA3dCmdHeader header; |
228 | SVGA3dCmdBindGBShader body; |
253 | SVGA3dCmdBindGBShader body; |
229 | } *cmd; |
254 | } *cmd; |
230 | struct ttm_buffer_object *bo = val_buf->bo; |
255 | struct ttm_buffer_object *bo = val_buf->bo; |
231 | 256 | ||
232 | BUG_ON(bo->mem.mem_type != VMW_PL_MOB); |
257 | BUG_ON(bo->mem.mem_type != VMW_PL_MOB); |
233 | 258 | ||
234 | cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd)); |
259 | cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd)); |
235 | if (unlikely(cmd == NULL)) { |
260 | if (unlikely(cmd == NULL)) { |
236 | DRM_ERROR("Failed reserving FIFO space for shader " |
261 | DRM_ERROR("Failed reserving FIFO space for shader " |
237 | "binding.\n"); |
262 | "binding.\n"); |
238 | return -ENOMEM; |
263 | return -ENOMEM; |
239 | } |
264 | } |
240 | 265 | ||
241 | cmd->header.id = SVGA_3D_CMD_BIND_GB_SHADER; |
266 | cmd->header.id = SVGA_3D_CMD_BIND_GB_SHADER; |
242 | cmd->header.size = sizeof(cmd->body); |
267 | cmd->header.size = sizeof(cmd->body); |
243 | cmd->body.shid = res->id; |
268 | cmd->body.shid = res->id; |
244 | cmd->body.mobid = bo->mem.start; |
269 | cmd->body.mobid = bo->mem.start; |
245 | cmd->body.offsetInBytes = 0; |
270 | cmd->body.offsetInBytes = res->backup_offset; |
246 | res->backup_dirty = false; |
271 | res->backup_dirty = false; |
247 | vmw_fifo_commit(dev_priv, sizeof(*cmd)); |
272 | vmw_fifo_commit(dev_priv, sizeof(*cmd)); |
248 | 273 | ||
249 | return 0; |
274 | return 0; |
250 | } |
275 | } |
251 | 276 | ||
252 | static int vmw_gb_shader_unbind(struct vmw_resource *res, |
277 | static int vmw_gb_shader_unbind(struct vmw_resource *res, |
253 | bool readback, |
278 | bool readback, |
254 | struct ttm_validate_buffer *val_buf) |
279 | struct ttm_validate_buffer *val_buf) |
255 | { |
280 | { |
256 | struct vmw_private *dev_priv = res->dev_priv; |
281 | struct vmw_private *dev_priv = res->dev_priv; |
257 | struct { |
282 | struct { |
258 | SVGA3dCmdHeader header; |
283 | SVGA3dCmdHeader header; |
259 | SVGA3dCmdBindGBShader body; |
284 | SVGA3dCmdBindGBShader body; |
260 | } *cmd; |
285 | } *cmd; |
261 | struct vmw_fence_obj *fence; |
286 | struct vmw_fence_obj *fence; |
262 | 287 | ||
263 | BUG_ON(res->backup->base.mem.mem_type != VMW_PL_MOB); |
288 | BUG_ON(res->backup->base.mem.mem_type != VMW_PL_MOB); |
264 | 289 | ||
265 | cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd)); |
290 | cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd)); |
266 | if (unlikely(cmd == NULL)) { |
291 | if (unlikely(cmd == NULL)) { |
267 | DRM_ERROR("Failed reserving FIFO space for shader " |
292 | DRM_ERROR("Failed reserving FIFO space for shader " |
268 | "unbinding.\n"); |
293 | "unbinding.\n"); |
269 | return -ENOMEM; |
294 | return -ENOMEM; |
270 | } |
295 | } |
271 | 296 | ||
272 | cmd->header.id = SVGA_3D_CMD_BIND_GB_SHADER; |
297 | cmd->header.id = SVGA_3D_CMD_BIND_GB_SHADER; |
273 | cmd->header.size = sizeof(cmd->body); |
298 | cmd->header.size = sizeof(cmd->body); |
274 | cmd->body.shid = res->id; |
299 | cmd->body.shid = res->id; |
275 | cmd->body.mobid = SVGA3D_INVALID_ID; |
300 | cmd->body.mobid = SVGA3D_INVALID_ID; |
276 | cmd->body.offsetInBytes = 0; |
301 | cmd->body.offsetInBytes = 0; |
277 | vmw_fifo_commit(dev_priv, sizeof(*cmd)); |
302 | vmw_fifo_commit(dev_priv, sizeof(*cmd)); |
278 | 303 | ||
279 | /* |
304 | /* |
280 | * Create a fence object and fence the backup buffer. |
305 | * Create a fence object and fence the backup buffer. |
281 | */ |
306 | */ |
282 | 307 | ||
283 | (void) vmw_execbuf_fence_commands(NULL, dev_priv, |
308 | (void) vmw_execbuf_fence_commands(NULL, dev_priv, |
284 | &fence, NULL); |
309 | &fence, NULL); |
285 | 310 | ||
286 | vmw_fence_single_bo(val_buf->bo, fence); |
311 | vmw_fence_single_bo(val_buf->bo, fence); |
287 | 312 | ||
288 | if (likely(fence != NULL)) |
313 | if (likely(fence != NULL)) |
289 | vmw_fence_obj_unreference(&fence); |
314 | vmw_fence_obj_unreference(&fence); |
290 | 315 | ||
291 | return 0; |
316 | return 0; |
292 | } |
317 | } |
293 | 318 | ||
294 | static int vmw_gb_shader_destroy(struct vmw_resource *res) |
319 | static int vmw_gb_shader_destroy(struct vmw_resource *res) |
295 | { |
320 | { |
296 | struct vmw_private *dev_priv = res->dev_priv; |
321 | struct vmw_private *dev_priv = res->dev_priv; |
297 | struct { |
322 | struct { |
298 | SVGA3dCmdHeader header; |
323 | SVGA3dCmdHeader header; |
299 | SVGA3dCmdDestroyGBShader body; |
324 | SVGA3dCmdDestroyGBShader body; |
300 | } *cmd; |
325 | } *cmd; |
301 | 326 | ||
302 | if (likely(res->id == -1)) |
327 | if (likely(res->id == -1)) |
303 | return 0; |
328 | return 0; |
304 | 329 | ||
305 | mutex_lock(&dev_priv->binding_mutex); |
330 | mutex_lock(&dev_priv->binding_mutex); |
306 | vmw_context_binding_res_list_scrub(&res->binding_head); |
331 | vmw_binding_res_list_scrub(&res->binding_head); |
307 | 332 | ||
308 | cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd)); |
333 | cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd)); |
309 | if (unlikely(cmd == NULL)) { |
334 | if (unlikely(cmd == NULL)) { |
310 | DRM_ERROR("Failed reserving FIFO space for shader " |
335 | DRM_ERROR("Failed reserving FIFO space for shader " |
311 | "destruction.\n"); |
336 | "destruction.\n"); |
312 | mutex_unlock(&dev_priv->binding_mutex); |
337 | mutex_unlock(&dev_priv->binding_mutex); |
313 | return -ENOMEM; |
338 | return -ENOMEM; |
314 | } |
339 | } |
315 | 340 | ||
316 | cmd->header.id = SVGA_3D_CMD_DESTROY_GB_SHADER; |
341 | cmd->header.id = SVGA_3D_CMD_DESTROY_GB_SHADER; |
317 | cmd->header.size = sizeof(cmd->body); |
342 | cmd->header.size = sizeof(cmd->body); |
318 | cmd->body.shid = res->id; |
343 | cmd->body.shid = res->id; |
319 | vmw_fifo_commit(dev_priv, sizeof(*cmd)); |
344 | vmw_fifo_commit(dev_priv, sizeof(*cmd)); |
320 | mutex_unlock(&dev_priv->binding_mutex); |
345 | mutex_unlock(&dev_priv->binding_mutex); |
321 | vmw_resource_release_id(res); |
346 | vmw_resource_release_id(res); |
322 | vmw_3d_resource_dec(dev_priv, false); |
347 | vmw_fifo_resource_dec(dev_priv); |
323 | 348 | ||
324 | return 0; |
349 | return 0; |
325 | } |
350 | } |
326 | 351 | ||
327 | /** |
352 | /** |
328 | * User-space shader management: |
353 | * User-space shader management: |
329 | */ |
354 | */ |
330 | 355 | ||
331 | static struct vmw_resource * |
356 | static struct vmw_resource * |
332 | vmw_user_shader_base_to_res(struct ttm_base_object *base) |
357 | vmw_user_shader_base_to_res(struct ttm_base_object *base) |
333 | { |
358 | { |
334 | return &(container_of(base, struct vmw_user_shader, base)-> |
359 | return &(container_of(base, struct vmw_user_shader, base)-> |
335 | shader.res); |
360 | shader.res); |
336 | } |
361 | } |
337 | 362 | ||
338 | static void vmw_user_shader_free(struct vmw_resource *res) |
363 | static void vmw_user_shader_free(struct vmw_resource *res) |
339 | { |
364 | { |
340 | struct vmw_user_shader *ushader = |
365 | struct vmw_user_shader *ushader = |
341 | container_of(res, struct vmw_user_shader, shader.res); |
366 | container_of(res, struct vmw_user_shader, shader.res); |
342 | struct vmw_private *dev_priv = res->dev_priv; |
367 | struct vmw_private *dev_priv = res->dev_priv; |
343 | 368 | ||
344 | ttm_base_object_kfree(ushader, base); |
369 | ttm_base_object_kfree(ushader, base); |
345 | ttm_mem_global_free(vmw_mem_glob(dev_priv), |
370 | ttm_mem_global_free(vmw_mem_glob(dev_priv), |
346 | vmw_user_shader_size); |
371 | vmw_user_shader_size); |
347 | } |
372 | } |
348 | 373 | ||
349 | /** |
374 | /** |
350 | * This function is called when user space has no more references on the |
375 | * This function is called when user space has no more references on the |
351 | * base object. It releases the base-object's reference on the resource object. |
376 | * base object. It releases the base-object's reference on the resource object. |
352 | */ |
377 | */ |
353 | 378 | ||
354 | static void vmw_user_shader_base_release(struct ttm_base_object **p_base) |
379 | static void vmw_user_shader_base_release(struct ttm_base_object **p_base) |
355 | { |
380 | { |
356 | struct ttm_base_object *base = *p_base; |
381 | struct ttm_base_object *base = *p_base; |
357 | struct vmw_resource *res = vmw_user_shader_base_to_res(base); |
382 | struct vmw_resource *res = vmw_user_shader_base_to_res(base); |
358 | 383 | ||
359 | *p_base = NULL; |
384 | *p_base = NULL; |
360 | vmw_resource_unreference(&res); |
385 | vmw_resource_unreference(&res); |
361 | } |
386 | } |
362 | 387 | ||
363 | int vmw_shader_destroy_ioctl(struct drm_device *dev, void *data, |
388 | int vmw_shader_destroy_ioctl(struct drm_device *dev, void *data, |
364 | struct drm_file *file_priv) |
389 | struct drm_file *file_priv) |
365 | { |
390 | { |
366 | struct drm_vmw_shader_arg *arg = (struct drm_vmw_shader_arg *)data; |
391 | struct drm_vmw_shader_arg *arg = (struct drm_vmw_shader_arg *)data; |
367 | struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile; |
392 | struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile; |
368 | 393 | ||
369 | return ttm_ref_object_base_unref(tfile, arg->handle, |
394 | return ttm_ref_object_base_unref(tfile, arg->handle, |
370 | TTM_REF_USAGE); |
395 | TTM_REF_USAGE); |
371 | } |
396 | } |
372 | 397 | ||
373 | static int vmw_user_shader_alloc(struct vmw_private *dev_priv, |
398 | static int vmw_user_shader_alloc(struct vmw_private *dev_priv, |
374 | struct vmw_dma_buffer *buffer, |
399 | struct vmw_dma_buffer *buffer, |
375 | size_t shader_size, |
400 | size_t shader_size, |
376 | size_t offset, |
401 | size_t offset, |
377 | SVGA3dShaderType shader_type, |
402 | SVGA3dShaderType shader_type, |
- | 403 | uint8_t num_input_sig, |
|
- | 404 | uint8_t num_output_sig, |
|
378 | struct ttm_object_file *tfile, |
405 | struct ttm_object_file *tfile, |
379 | u32 *handle) |
406 | u32 *handle) |
380 | { |
407 | { |
381 | struct vmw_user_shader *ushader; |
408 | struct vmw_user_shader *ushader; |
382 | struct vmw_resource *res, *tmp; |
409 | struct vmw_resource *res, *tmp; |
383 | int ret; |
410 | int ret; |
384 | 411 | ||
385 | /* |
412 | /* |
386 | * Approximate idr memory usage with 128 bytes. It will be limited |
413 | * Approximate idr memory usage with 128 bytes. It will be limited |
387 | * by maximum number_of shaders anyway. |
414 | * by maximum number_of shaders anyway. |
388 | */ |
415 | */ |
389 | if (unlikely(vmw_user_shader_size == 0)) |
416 | if (unlikely(vmw_user_shader_size == 0)) |
390 | vmw_user_shader_size = |
417 | vmw_user_shader_size = |
391 | ttm_round_pot(sizeof(struct vmw_user_shader)) + 128; |
418 | ttm_round_pot(sizeof(struct vmw_user_shader)) + 128; |
392 | 419 | ||
393 | ret = ttm_mem_global_alloc(vmw_mem_glob(dev_priv), |
420 | ret = ttm_mem_global_alloc(vmw_mem_glob(dev_priv), |
394 | vmw_user_shader_size, |
421 | vmw_user_shader_size, |
395 | false, true); |
422 | false, true); |
396 | if (unlikely(ret != 0)) { |
423 | if (unlikely(ret != 0)) { |
397 | if (ret != -ERESTARTSYS) |
424 | if (ret != -ERESTARTSYS) |
398 | DRM_ERROR("Out of graphics memory for shader " |
425 | DRM_ERROR("Out of graphics memory for shader " |
399 | "creation.\n"); |
426 | "creation.\n"); |
400 | goto out; |
427 | goto out; |
401 | } |
428 | } |
402 | 429 | ||
403 | ushader = kzalloc(sizeof(*ushader), GFP_KERNEL); |
430 | ushader = kzalloc(sizeof(*ushader), GFP_KERNEL); |
404 | if (unlikely(ushader == NULL)) { |
431 | if (unlikely(ushader == NULL)) { |
405 | ttm_mem_global_free(vmw_mem_glob(dev_priv), |
432 | ttm_mem_global_free(vmw_mem_glob(dev_priv), |
406 | vmw_user_shader_size); |
433 | vmw_user_shader_size); |
407 | ret = -ENOMEM; |
434 | ret = -ENOMEM; |
408 | goto out; |
435 | goto out; |
409 | } |
436 | } |
410 | 437 | ||
411 | res = &ushader->shader.res; |
438 | res = &ushader->shader.res; |
412 | ushader->base.shareable = false; |
439 | ushader->base.shareable = false; |
413 | ushader->base.tfile = NULL; |
440 | ushader->base.tfile = NULL; |
414 | 441 | ||
415 | /* |
442 | /* |
416 | * From here on, the destructor takes over resource freeing. |
443 | * From here on, the destructor takes over resource freeing. |
417 | */ |
444 | */ |
418 | 445 | ||
419 | ret = vmw_gb_shader_init(dev_priv, res, shader_size, |
446 | ret = vmw_gb_shader_init(dev_priv, res, shader_size, |
420 | offset, shader_type, buffer, |
447 | offset, shader_type, num_input_sig, |
- | 448 | num_output_sig, buffer, |
|
421 | vmw_user_shader_free); |
449 | vmw_user_shader_free); |
422 | if (unlikely(ret != 0)) |
450 | if (unlikely(ret != 0)) |
423 | goto out; |
451 | goto out; |
424 | 452 | ||
425 | tmp = vmw_resource_reference(res); |
453 | tmp = vmw_resource_reference(res); |
426 | ret = ttm_base_object_init(tfile, &ushader->base, false, |
454 | ret = ttm_base_object_init(tfile, &ushader->base, false, |
427 | VMW_RES_SHADER, |
455 | VMW_RES_SHADER, |
428 | &vmw_user_shader_base_release, NULL); |
456 | &vmw_user_shader_base_release, NULL); |
429 | 457 | ||
430 | if (unlikely(ret != 0)) { |
458 | if (unlikely(ret != 0)) { |
431 | vmw_resource_unreference(&tmp); |
459 | vmw_resource_unreference(&tmp); |
432 | goto out_err; |
460 | goto out_err; |
433 | } |
461 | } |
434 | 462 | ||
435 | if (handle) |
463 | if (handle) |
436 | *handle = ushader->base.hash.key; |
464 | *handle = ushader->base.hash.key; |
437 | out_err: |
465 | out_err: |
438 | vmw_resource_unreference(&res); |
466 | vmw_resource_unreference(&res); |
439 | out: |
467 | out: |
440 | return ret; |
468 | return ret; |
441 | } |
469 | } |
442 | 470 | ||
- | 471 | ||
- | 472 | static struct vmw_resource *vmw_shader_alloc(struct vmw_private *dev_priv, |
|
- | 473 | struct vmw_dma_buffer *buffer, |
|
- | 474 | size_t shader_size, |
|
- | 475 | size_t offset, |
|
- | 476 | SVGA3dShaderType shader_type) |
|
- | 477 | { |
|
- | 478 | struct vmw_shader *shader; |
|
- | 479 | struct vmw_resource *res; |
|
- | 480 | int ret; |
|
- | 481 | ||
- | 482 | /* |
|
- | 483 | * Approximate idr memory usage with 128 bytes. It will be limited |
|
- | 484 | * by maximum number_of shaders anyway. |
|
- | 485 | */ |
|
- | 486 | if (unlikely(vmw_shader_size == 0)) |
|
- | 487 | vmw_shader_size = |
|
- | 488 | ttm_round_pot(sizeof(struct vmw_shader)) + 128; |
|
- | 489 | ||
- | 490 | ret = ttm_mem_global_alloc(vmw_mem_glob(dev_priv), |
|
- | 491 | vmw_shader_size, |
|
- | 492 | false, true); |
|
- | 493 | if (unlikely(ret != 0)) { |
|
- | 494 | if (ret != -ERESTARTSYS) |
|
- | 495 | DRM_ERROR("Out of graphics memory for shader " |
|
- | 496 | "creation.\n"); |
|
- | 497 | goto out_err; |
|
- | 498 | } |
|
- | 499 | ||
- | 500 | shader = kzalloc(sizeof(*shader), GFP_KERNEL); |
|
- | 501 | if (unlikely(shader == NULL)) { |
|
- | 502 | ttm_mem_global_free(vmw_mem_glob(dev_priv), |
|
- | 503 | vmw_shader_size); |
|
- | 504 | ret = -ENOMEM; |
|
- | 505 | goto out_err; |
|
- | 506 | } |
|
- | 507 | ||
- | 508 | res = &shader->res; |
|
- | 509 | ||
- | 510 | /* |
|
- | 511 | * From here on, the destructor takes over resource freeing. |
|
- | 512 | */ |
|
- | 513 | ret = vmw_gb_shader_init(dev_priv, res, shader_size, |
|
- | 514 | offset, shader_type, 0, 0, buffer, |
|
- | 515 | vmw_shader_free); |
|
- | 516 | ||
- | 517 | out_err: |
|
- | 518 | return ret ? ERR_PTR(ret) : res; |
|
- | 519 | } |
|
- | 520 | ||
443 | 521 | ||
- | 522 | static int vmw_shader_define(struct drm_device *dev, struct drm_file *file_priv, |
|
- | 523 | enum drm_vmw_shader_type shader_type_drm, |
|
- | 524 | u32 buffer_handle, size_t size, size_t offset, |
|
444 | int vmw_shader_define_ioctl(struct drm_device *dev, void *data, |
525 | uint8_t num_input_sig, uint8_t num_output_sig, |
445 | struct drm_file *file_priv) |
526 | uint32_t *shader_handle) |
446 | { |
527 | { |
447 | struct vmw_private *dev_priv = vmw_priv(dev); |
- | |
448 | struct drm_vmw_shader_create_arg *arg = |
- | |
449 | (struct drm_vmw_shader_create_arg *)data; |
528 | struct vmw_private *dev_priv = vmw_priv(dev); |
450 | struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile; |
529 | struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile; |
451 | struct vmw_dma_buffer *buffer = NULL; |
530 | struct vmw_dma_buffer *buffer = NULL; |
452 | SVGA3dShaderType shader_type; |
531 | SVGA3dShaderType shader_type; |
453 | int ret; |
532 | int ret; |
454 | 533 | ||
455 | if (arg->buffer_handle != SVGA3D_INVALID_ID) { |
534 | if (buffer_handle != SVGA3D_INVALID_ID) { |
456 | ret = vmw_user_dmabuf_lookup(tfile, arg->buffer_handle, |
535 | ret = vmw_user_dmabuf_lookup(tfile, buffer_handle, |
457 | &buffer); |
536 | &buffer, NULL); |
458 | if (unlikely(ret != 0)) { |
537 | if (unlikely(ret != 0)) { |
459 | DRM_ERROR("Could not find buffer for shader " |
538 | DRM_ERROR("Could not find buffer for shader " |
460 | "creation.\n"); |
539 | "creation.\n"); |
461 | return ret; |
540 | return ret; |
462 | } |
541 | } |
463 | 542 | ||
464 | if ((u64)buffer->base.num_pages * PAGE_SIZE < |
543 | if ((u64)buffer->base.num_pages * PAGE_SIZE < |
465 | (u64)arg->size + (u64)arg->offset) { |
544 | (u64)size + (u64)offset) { |
466 | DRM_ERROR("Illegal buffer- or shader size.\n"); |
545 | DRM_ERROR("Illegal buffer- or shader size.\n"); |
467 | ret = -EINVAL; |
546 | ret = -EINVAL; |
468 | goto out_bad_arg; |
547 | goto out_bad_arg; |
469 | } |
548 | } |
470 | } |
549 | } |
471 | 550 | ||
472 | switch (arg->shader_type) { |
551 | switch (shader_type_drm) { |
473 | case drm_vmw_shader_type_vs: |
552 | case drm_vmw_shader_type_vs: |
474 | shader_type = SVGA3D_SHADERTYPE_VS; |
553 | shader_type = SVGA3D_SHADERTYPE_VS; |
475 | break; |
554 | break; |
476 | case drm_vmw_shader_type_ps: |
555 | case drm_vmw_shader_type_ps: |
477 | shader_type = SVGA3D_SHADERTYPE_PS; |
556 | shader_type = SVGA3D_SHADERTYPE_PS; |
478 | break; |
557 | break; |
479 | case drm_vmw_shader_type_gs: |
- | |
480 | shader_type = SVGA3D_SHADERTYPE_GS; |
- | |
481 | break; |
- | |
482 | default: |
558 | default: |
483 | DRM_ERROR("Illegal shader type.\n"); |
559 | DRM_ERROR("Illegal shader type.\n"); |
484 | ret = -EINVAL; |
560 | ret = -EINVAL; |
485 | goto out_bad_arg; |
561 | goto out_bad_arg; |
486 | } |
562 | } |
487 | 563 | ||
488 | ret = ttm_read_lock(&dev_priv->reservation_sem, true); |
564 | ret = ttm_read_lock(&dev_priv->reservation_sem, true); |
489 | if (unlikely(ret != 0)) |
565 | if (unlikely(ret != 0)) |
490 | goto out_bad_arg; |
566 | goto out_bad_arg; |
491 | 567 | ||
- | 568 | ret = vmw_user_shader_alloc(dev_priv, buffer, size, offset, |
|
492 | ret = vmw_user_shader_alloc(dev_priv, buffer, arg->size, arg->offset, |
569 | shader_type, num_input_sig, |
493 | shader_type, tfile, &arg->shader_handle); |
570 | num_output_sig, tfile, shader_handle); |
494 | 571 | ||
495 | ttm_read_unlock(&dev_priv->reservation_sem); |
572 | ttm_read_unlock(&dev_priv->reservation_sem); |
496 | out_bad_arg: |
573 | out_bad_arg: |
497 | vmw_dmabuf_unreference(&buffer); |
574 | vmw_dmabuf_unreference(&buffer); |
498 | return ret; |
575 | return ret; |
499 | } |
576 | } |
500 | 577 | ||
501 | /** |
578 | /** |
502 | * vmw_compat_shader_id_ok - Check whether a compat shader user key and |
579 | * vmw_shader_id_ok - Check whether a compat shader user key and |
503 | * shader type are within valid bounds. |
580 | * shader type are within valid bounds. |
504 | * |
581 | * |
505 | * @user_key: User space id of the shader. |
582 | * @user_key: User space id of the shader. |
506 | * @shader_type: Shader type. |
583 | * @shader_type: Shader type. |
507 | * |
584 | * |
508 | * Returns true if valid false if not. |
585 | * Returns true if valid false if not. |
509 | */ |
586 | */ |
510 | static bool vmw_compat_shader_id_ok(u32 user_key, SVGA3dShaderType shader_type) |
587 | static bool vmw_shader_id_ok(u32 user_key, SVGA3dShaderType shader_type) |
511 | { |
588 | { |
512 | return user_key <= ((1 << 20) - 1) && (unsigned) shader_type < 16; |
589 | return user_key <= ((1 << 20) - 1) && (unsigned) shader_type < 16; |
513 | } |
590 | } |
514 | 591 | ||
515 | /** |
592 | /** |
516 | * vmw_compat_shader_key - Compute a hash key suitable for a compat shader. |
593 | * vmw_shader_key - Compute a hash key suitable for a compat shader. |
517 | * |
594 | * |
518 | * @user_key: User space id of the shader. |
595 | * @user_key: User space id of the shader. |
519 | * @shader_type: Shader type. |
596 | * @shader_type: Shader type. |
520 | * |
597 | * |
521 | * Returns a hash key suitable for a command buffer managed resource |
598 | * Returns a hash key suitable for a command buffer managed resource |
522 | * manager hash table. |
599 | * manager hash table. |
523 | */ |
600 | */ |
524 | static u32 vmw_compat_shader_key(u32 user_key, SVGA3dShaderType shader_type) |
601 | static u32 vmw_shader_key(u32 user_key, SVGA3dShaderType shader_type) |
525 | { |
602 | { |
526 | return user_key | (shader_type << 20); |
603 | return user_key | (shader_type << 20); |
527 | } |
604 | } |
528 | 605 | ||
529 | /** |
606 | /** |
530 | * vmw_compat_shader_remove - Stage a compat shader for removal. |
607 | * vmw_shader_remove - Stage a compat shader for removal. |
531 | * |
608 | * |
532 | * @man: Pointer to the compat shader manager identifying the shader namespace. |
609 | * @man: Pointer to the compat shader manager identifying the shader namespace. |
533 | * @user_key: The key that is used to identify the shader. The key is |
610 | * @user_key: The key that is used to identify the shader. The key is |
534 | * unique to the shader type. |
611 | * unique to the shader type. |
535 | * @shader_type: Shader type. |
612 | * @shader_type: Shader type. |
536 | * @list: Caller's list of staged command buffer resource actions. |
613 | * @list: Caller's list of staged command buffer resource actions. |
537 | */ |
614 | */ |
538 | int vmw_compat_shader_remove(struct vmw_cmdbuf_res_manager *man, |
615 | int vmw_shader_remove(struct vmw_cmdbuf_res_manager *man, |
539 | u32 user_key, SVGA3dShaderType shader_type, |
616 | u32 user_key, SVGA3dShaderType shader_type, |
540 | struct list_head *list) |
617 | struct list_head *list) |
541 | { |
618 | { |
- | 619 | struct vmw_resource *dummy; |
|
- | 620 | ||
542 | if (!vmw_compat_shader_id_ok(user_key, shader_type)) |
621 | if (!vmw_shader_id_ok(user_key, shader_type)) |
543 | return -EINVAL; |
622 | return -EINVAL; |
544 | 623 | ||
545 | return vmw_cmdbuf_res_remove(man, vmw_cmdbuf_res_compat_shader, |
624 | return vmw_cmdbuf_res_remove(man, vmw_cmdbuf_res_shader, |
546 | vmw_compat_shader_key(user_key, |
- | |
547 | shader_type), |
625 | vmw_shader_key(user_key, shader_type), |
548 | list); |
626 | list, &dummy); |
549 | } |
627 | } |
550 | 628 | ||
551 | /** |
629 | /** |
552 | * vmw_compat_shader_add - Create a compat shader and stage it for addition |
630 | * vmw_compat_shader_add - Create a compat shader and stage it for addition |
553 | * as a command buffer managed resource. |
631 | * as a command buffer managed resource. |
554 | * |
632 | * |
555 | * @man: Pointer to the compat shader manager identifying the shader namespace. |
633 | * @man: Pointer to the compat shader manager identifying the shader namespace. |
556 | * @user_key: The key that is used to identify the shader. The key is |
634 | * @user_key: The key that is used to identify the shader. The key is |
557 | * unique to the shader type. |
635 | * unique to the shader type. |
558 | * @bytecode: Pointer to the bytecode of the shader. |
636 | * @bytecode: Pointer to the bytecode of the shader. |
559 | * @shader_type: Shader type. |
637 | * @shader_type: Shader type. |
560 | * @tfile: Pointer to a struct ttm_object_file that the guest-backed shader is |
638 | * @tfile: Pointer to a struct ttm_object_file that the guest-backed shader is |
561 | * to be created with. |
639 | * to be created with. |
562 | * @list: Caller's list of staged command buffer resource actions. |
640 | * @list: Caller's list of staged command buffer resource actions. |
563 | * |
641 | * |
564 | */ |
642 | */ |
565 | int vmw_compat_shader_add(struct vmw_private *dev_priv, |
643 | int vmw_compat_shader_add(struct vmw_private *dev_priv, |
566 | struct vmw_cmdbuf_res_manager *man, |
644 | struct vmw_cmdbuf_res_manager *man, |
567 | u32 user_key, const void *bytecode, |
645 | u32 user_key, const void *bytecode, |
568 | SVGA3dShaderType shader_type, |
646 | SVGA3dShaderType shader_type, |
569 | size_t size, |
647 | size_t size, |
570 | struct list_head *list) |
648 | struct list_head *list) |
571 | { |
649 | { |
572 | struct vmw_dma_buffer *buf; |
650 | struct vmw_dma_buffer *buf; |
573 | struct ttm_bo_kmap_obj map; |
651 | struct ttm_bo_kmap_obj map; |
574 | bool is_iomem; |
652 | bool is_iomem; |
575 | int ret; |
653 | int ret; |
576 | struct vmw_resource *res; |
654 | struct vmw_resource *res; |
577 | 655 | ||
578 | if (!vmw_compat_shader_id_ok(user_key, shader_type)) |
656 | if (!vmw_shader_id_ok(user_key, shader_type)) |
579 | return -EINVAL; |
657 | return -EINVAL; |
580 | 658 | ||
581 | /* Allocate and pin a DMA buffer */ |
659 | /* Allocate and pin a DMA buffer */ |
582 | buf = kzalloc(sizeof(*buf), GFP_KERNEL); |
660 | buf = kzalloc(sizeof(*buf), GFP_KERNEL); |
583 | if (unlikely(buf == NULL)) |
661 | if (unlikely(buf == NULL)) |
584 | return -ENOMEM; |
662 | return -ENOMEM; |
585 | 663 | ||
586 | ret = vmw_dmabuf_init(dev_priv, buf, size, &vmw_sys_ne_placement, |
664 | ret = vmw_dmabuf_init(dev_priv, buf, size, &vmw_sys_ne_placement, |
587 | true, vmw_dmabuf_bo_free); |
665 | true, vmw_dmabuf_bo_free); |
588 | if (unlikely(ret != 0)) |
666 | if (unlikely(ret != 0)) |
589 | goto out; |
667 | goto out; |
590 | 668 | ||
591 | ret = ttm_bo_reserve(&buf->base, false, true, false, NULL); |
669 | ret = ttm_bo_reserve(&buf->base, false, true, false, NULL); |
592 | if (unlikely(ret != 0)) |
670 | if (unlikely(ret != 0)) |
593 | goto no_reserve; |
671 | goto no_reserve; |
594 | 672 | ||
595 | /* Map and copy shader bytecode. */ |
673 | /* Map and copy shader bytecode. */ |
596 | ret = ttm_bo_kmap(&buf->base, 0, PAGE_ALIGN(size) >> PAGE_SHIFT, |
674 | ret = ttm_bo_kmap(&buf->base, 0, PAGE_ALIGN(size) >> PAGE_SHIFT, |
597 | &map); |
675 | &map); |
598 | if (unlikely(ret != 0)) { |
676 | if (unlikely(ret != 0)) { |
599 | ttm_bo_unreserve(&buf->base); |
677 | ttm_bo_unreserve(&buf->base); |
600 | goto no_reserve; |
678 | goto no_reserve; |
601 | } |
679 | } |
602 | 680 | ||
603 | memcpy(ttm_kmap_obj_virtual(&map, &is_iomem), bytecode, size); |
681 | memcpy(ttm_kmap_obj_virtual(&map, &is_iomem), bytecode, size); |
604 | WARN_ON(is_iomem); |
682 | WARN_ON(is_iomem); |
605 | 683 | ||
606 | ttm_bo_kunmap(&map); |
684 | ttm_bo_kunmap(&map); |
607 | ret = ttm_bo_validate(&buf->base, &vmw_sys_placement, false, true); |
685 | ret = ttm_bo_validate(&buf->base, &vmw_sys_placement, false, true); |
608 | WARN_ON(ret != 0); |
686 | WARN_ON(ret != 0); |
609 | ttm_bo_unreserve(&buf->base); |
687 | ttm_bo_unreserve(&buf->base); |
610 | 688 | ||
611 | res = vmw_shader_alloc(dev_priv, buf, size, 0, shader_type); |
689 | res = vmw_shader_alloc(dev_priv, buf, size, 0, shader_type); |
612 | if (unlikely(ret != 0)) |
690 | if (unlikely(ret != 0)) |
613 | goto no_reserve; |
691 | goto no_reserve; |
614 | 692 | ||
615 | ret = vmw_cmdbuf_res_add(man, vmw_cmdbuf_res_compat_shader, |
693 | ret = vmw_cmdbuf_res_add(man, vmw_cmdbuf_res_shader, |
616 | vmw_compat_shader_key(user_key, shader_type), |
694 | vmw_shader_key(user_key, shader_type), |
617 | res, list); |
695 | res, list); |
618 | vmw_resource_unreference(&res); |
696 | vmw_resource_unreference(&res); |
619 | no_reserve: |
697 | no_reserve: |
620 | vmw_dmabuf_unreference(&buf); |
698 | vmw_dmabuf_unreference(&buf); |
621 | out: |
699 | out: |
622 | return ret; |
700 | return ret; |
623 | } |
701 | } |
624 | 702 | ||
625 | /** |
703 | /** |
626 | * vmw_compat_shader_lookup - Look up a compat shader |
704 | * vmw_shader_lookup - Look up a compat shader |
627 | * |
705 | * |
628 | * @man: Pointer to the command buffer managed resource manager identifying |
706 | * @man: Pointer to the command buffer managed resource manager identifying |
629 | * the shader namespace. |
707 | * the shader namespace. |
630 | * @user_key: The user space id of the shader. |
708 | * @user_key: The user space id of the shader. |
631 | * @shader_type: The shader type. |
709 | * @shader_type: The shader type. |
632 | * |
710 | * |
633 | * Returns a refcounted pointer to a struct vmw_resource if the shader was |
711 | * Returns a refcounted pointer to a struct vmw_resource if the shader was |
634 | * found. An error pointer otherwise. |
712 | * found. An error pointer otherwise. |
635 | */ |
713 | */ |
636 | struct vmw_resource * |
714 | struct vmw_resource * |
637 | vmw_compat_shader_lookup(struct vmw_cmdbuf_res_manager *man, |
715 | vmw_shader_lookup(struct vmw_cmdbuf_res_manager *man, |
638 | u32 user_key, |
716 | u32 user_key, |
639 | SVGA3dShaderType shader_type) |
717 | SVGA3dShaderType shader_type) |
640 | { |
718 | { |
641 | if (!vmw_compat_shader_id_ok(user_key, shader_type)) |
719 | if (!vmw_shader_id_ok(user_key, shader_type)) |
642 | return ERR_PTR(-EINVAL); |
720 | return ERR_PTR(-EINVAL); |
643 | 721 | ||
644 | return vmw_cmdbuf_res_lookup(man, vmw_cmdbuf_res_compat_shader, |
722 | return vmw_cmdbuf_res_lookup(man, vmw_cmdbuf_res_shader, |
- | 723 | vmw_shader_key(user_key, shader_type)); |
|
- | 724 | } |
|
- | 725 | ||
- | 726 | int vmw_shader_define_ioctl(struct drm_device *dev, void *data, |
|
- | 727 | struct drm_file *file_priv) |
|
- | 728 | { |
|
- | 729 | struct drm_vmw_shader_create_arg *arg = |
|
- | 730 | (struct drm_vmw_shader_create_arg *)data; |
|
- | 731 | ||
- | 732 | return vmw_shader_define(dev, file_priv, arg->shader_type, |
|
- | 733 | arg->buffer_handle, |
|
- | 734 | arg->size, arg->offset, |
|
645 | vmw_compat_shader_key(user_key, |
735 | 0, 0, |
646 | shader_type)); |
736 | &arg->shader_handle); |
647 | } |
737 | } |
648 | #endif><>>><>=> |
738 | #endif><>>><>=> |
649 | > |
739 | > |