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 */
37struct 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 */
60static 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, delay_id: false, res_free,
69 func: &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(p_res: &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 */
94static 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 */
112static 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(p_res: &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 */
137int
138vmw_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(size: 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, simple: &usimple->simple,
168 data, res_free: 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, base: &usimple->base, shareable: false,
174 type: func->ttm_res_type,
175 refcount_release: &vmw_simple_resource_base_release);
176
177 if (ret) {
178 vmw_resource_unreference(p_res: &tmp);
179 goto out_err;
180 }
181
182 func->set_arg_handle(data, usimple->base.handle);
183out_err:
184 vmw_resource_unreference(p_res: &res);
185out_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 */
201struct vmw_resource *
202vmw_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, key: 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(error: -ESRCH);
216 }
217
218 if (ttm_base_object_type(base) != func->ttm_res_type) {
219 ttm_base_object_unref(p_base: &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(error: -EINVAL);
224 }
225
226 usimple = container_of(base, typeof(*usimple), base);
227 res = vmw_resource_reference(res: &usimple->simple.res);
228 ttm_base_object_unref(p_base: &base);
229
230 return res;
231}
232

source code of linux/drivers/gpu/drm/vmwgfx/vmwgfx_simple_resource.c