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 */ 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 */ 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 */ 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 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 * successfule. Error pointer otherwise. 200 */ 201 struct vmw_resource * 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