1 // SPDX-License-Identifier: GPL-2.0 OR MIT
2 /**************************************************************************
3 *
4 * Copyright 2016 VMware, Inc., Palo Alto, CA., USA
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
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
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
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,
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,
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
24 * USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 **************************************************************************/
27
28 #include "vmwgfx_drv.h"
29 #include "vmwgfx_resource_priv.h"
30
31 /**
32 * struct vmw_user_simple_resource - User-space simple resource struct
33 *
34 * @base: The TTM base object implementing user-space visibility.
35 * @simple: The embedded struct vmw_simple_resource.
36 */
37 struct vmw_user_simple_resource {
38 struct ttm_base_object base;
39 struct vmw_simple_resource simple;
40 /*
41 * Nothing to be placed after @simple, since size of @simple is
42 * unknown.
43 */
44 };
45
46
47 /**
48 * vmw_simple_resource_init - Initialize a simple resource object.
49 *
50 * @dev_priv: Pointer to a struct device private.
51 * @simple: The struct vmw_simple_resource to initialize.
52 * @data: Data passed to the information initialization function.
53 * @res_free: Function pointer to destroy the simple resource.
54 *
55 * Returns:
56 * 0 if succeeded.
57 * Negative error value if error, in which case the resource will have been
58 * freed.
59 */
vmw_simple_resource_init(struct vmw_private * dev_priv,struct vmw_simple_resource * simple,void * data,void (* res_free)(struct vmw_resource * res))60 static int vmw_simple_resource_init(struct vmw_private *dev_priv,
61 struct vmw_simple_resource *simple,
62 void *data,
63 void (*res_free)(struct vmw_resource *res))
64 {
65 struct vmw_resource *res = &simple->res;
66 int ret;
67
68 ret = vmw_resource_init(dev_priv, res, false, res_free,
69 &simple->func->res_func);
70
71 if (ret) {
72 res_free(res);
73 return ret;
74 }
75
76 ret = simple->func->init(res, data);
77 if (ret) {
78 vmw_resource_unreference(&res);
79 return ret;
80 }
81
82 simple->res.hw_destroy = simple->func->hw_destroy;
83
84 return 0;
85 }
86
87 /**
88 * vmw_simple_resource_free - Free a simple resource object.
89 *
90 * @res: The struct vmw_resource member of the simple resource object.
91 *
92 * Frees memory for the object.
93 */
vmw_simple_resource_free(struct vmw_resource * res)94 static void vmw_simple_resource_free(struct vmw_resource *res)
95 {
96 struct vmw_user_simple_resource *usimple =
97 container_of(res, struct vmw_user_simple_resource,
98 simple.res);
99
100 ttm_base_object_kfree(usimple, base);
101 }
102
103 /**
104 * vmw_simple_resource_base_release - TTM object release callback
105 *
106 * @p_base: The struct ttm_base_object member of the simple resource object.
107 *
108 * Called when the last reference to the embedded struct ttm_base_object is
109 * gone. Typically results in an object free, unless there are other
110 * references to the embedded struct vmw_resource.
111 */
vmw_simple_resource_base_release(struct ttm_base_object ** p_base)112 static void vmw_simple_resource_base_release(struct ttm_base_object **p_base)
113 {
114 struct ttm_base_object *base = *p_base;
115 struct vmw_user_simple_resource *usimple =
116 container_of(base, struct vmw_user_simple_resource, base);
117 struct vmw_resource *res = &usimple->simple.res;
118
119 *p_base = NULL;
120 vmw_resource_unreference(&res);
121 }
122
123 /**
124 * vmw_simple_resource_create_ioctl - Helper to set up an ioctl function to
125 * create a struct vmw_simple_resource.
126 *
127 * @dev: Pointer to a struct drm device.
128 * @data: Ioctl argument.
129 * @file_priv: Pointer to a struct drm_file identifying the caller.
130 * @func: Pointer to a struct vmw_simple_resource_func identifying the
131 * simple resource type.
132 *
133 * Returns:
134 * 0 if success,
135 * Negative error value on error.
136 */
137 int
vmw_simple_resource_create_ioctl(struct drm_device * dev,void * data,struct drm_file * file_priv,const struct vmw_simple_resource_func * func)138 vmw_simple_resource_create_ioctl(struct drm_device *dev, void *data,
139 struct drm_file *file_priv,
140 const struct vmw_simple_resource_func *func)
141 {
142 struct vmw_private *dev_priv = vmw_priv(dev);
143 struct vmw_user_simple_resource *usimple;
144 struct vmw_resource *res;
145 struct vmw_resource *tmp;
146 struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
147 size_t alloc_size;
148 int ret;
149
150 alloc_size = offsetof(struct vmw_user_simple_resource, simple) +
151 func->size;
152
153 usimple = kzalloc(alloc_size, GFP_KERNEL);
154 if (!usimple) {
155 ret = -ENOMEM;
156 goto out_ret;
157 }
158
159 usimple->simple.func = func;
160 res = &usimple->simple.res;
161 usimple->base.shareable = false;
162 usimple->base.tfile = NULL;
163
164 /*
165 * From here on, the destructor takes over resource freeing.
166 */
167 ret = vmw_simple_resource_init(dev_priv, &usimple->simple,
168 data, vmw_simple_resource_free);
169 if (ret)
170 goto out_ret;
171
172 tmp = vmw_resource_reference(res);
173 ret = ttm_base_object_init(tfile, &usimple->base, false,
174 func->ttm_res_type,
175 &vmw_simple_resource_base_release);
176
177 if (ret) {
178 vmw_resource_unreference(&tmp);
179 goto out_err;
180 }
181
182 func->set_arg_handle(data, usimple->base.handle);
183 out_err:
184 vmw_resource_unreference(&res);
185 out_ret:
186 return ret;
187 }
188
189 /**
190 * vmw_simple_resource_lookup - Look up a simple resource from its user-space
191 * handle.
192 *
193 * @tfile: struct ttm_object_file identifying the caller.
194 * @handle: The user-space handle.
195 * @func: The struct vmw_simple_resource_func identifying the simple resource
196 * type.
197 *
198 * Returns: Refcounted pointer to the embedded struct vmw_resource if
199 * successful. Error pointer otherwise.
200 */
201 struct vmw_resource *
vmw_simple_resource_lookup(struct ttm_object_file * tfile,uint32_t handle,const struct vmw_simple_resource_func * func)202 vmw_simple_resource_lookup(struct ttm_object_file *tfile,
203 uint32_t handle,
204 const struct vmw_simple_resource_func *func)
205 {
206 struct vmw_user_simple_resource *usimple;
207 struct ttm_base_object *base;
208 struct vmw_resource *res;
209
210 base = ttm_base_object_lookup(tfile, handle);
211 if (!base) {
212 VMW_DEBUG_USER("Invalid %s handle 0x%08lx.\n",
213 func->res_func.type_name,
214 (unsigned long) handle);
215 return ERR_PTR(-ESRCH);
216 }
217
218 if (ttm_base_object_type(base) != func->ttm_res_type) {
219 ttm_base_object_unref(&base);
220 VMW_DEBUG_USER("Invalid type of %s handle 0x%08lx.\n",
221 func->res_func.type_name,
222 (unsigned long) handle);
223 return ERR_PTR(-EINVAL);
224 }
225
226 usimple = container_of(base, typeof(*usimple), base);
227 res = vmw_resource_reference(&usimple->simple.res);
228 ttm_base_object_unref(&base);
229
230 return res;
231 }
232