1 1.1 riastrad /* $NetBSD: vmwgfx_simple_resource.c,v 1.2 2021/12/18 23:45:45 riastradh Exp $ */ 2 1.1 riastrad 3 1.1 riastrad // SPDX-License-Identifier: GPL-2.0 OR MIT 4 1.1 riastrad /************************************************************************** 5 1.1 riastrad * 6 1.1 riastrad * Copyright 2016 VMware, Inc., Palo Alto, CA., USA 7 1.1 riastrad * 8 1.1 riastrad * Permission is hereby granted, free of charge, to any person obtaining a 9 1.1 riastrad * copy of this software and associated documentation files (the 10 1.1 riastrad * "Software"), to deal in the Software without restriction, including 11 1.1 riastrad * without limitation the rights to use, copy, modify, merge, publish, 12 1.1 riastrad * distribute, sub license, and/or sell copies of the Software, and to 13 1.1 riastrad * permit persons to whom the Software is furnished to do so, subject to 14 1.1 riastrad * the following conditions: 15 1.1 riastrad * 16 1.1 riastrad * The above copyright notice and this permission notice (including the 17 1.1 riastrad * next paragraph) shall be included in all copies or substantial portions 18 1.1 riastrad * of the Software. 19 1.1 riastrad * 20 1.1 riastrad * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 1.1 riastrad * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 1.1 riastrad * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 23 1.1 riastrad * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, 24 1.1 riastrad * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 25 1.1 riastrad * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 26 1.1 riastrad * USE OR OTHER DEALINGS IN THE SOFTWARE. 27 1.1 riastrad * 28 1.1 riastrad **************************************************************************/ 29 1.1 riastrad 30 1.1 riastrad #include <sys/cdefs.h> 31 1.1 riastrad __KERNEL_RCSID(0, "$NetBSD: vmwgfx_simple_resource.c,v 1.2 2021/12/18 23:45:45 riastradh Exp $"); 32 1.1 riastrad 33 1.1 riastrad #include "vmwgfx_drv.h" 34 1.1 riastrad #include "vmwgfx_resource_priv.h" 35 1.1 riastrad 36 1.1 riastrad /** 37 1.1 riastrad * struct vmw_user_simple_resource - User-space simple resource struct 38 1.1 riastrad * 39 1.1 riastrad * @base: The TTM base object implementing user-space visibility. 40 1.1 riastrad * @account_size: How much memory was accounted for this object. 41 1.1 riastrad * @simple: The embedded struct vmw_simple_resource. 42 1.1 riastrad */ 43 1.1 riastrad struct vmw_user_simple_resource { 44 1.1 riastrad struct ttm_base_object base; 45 1.1 riastrad size_t account_size; 46 1.1 riastrad struct vmw_simple_resource simple; 47 1.1 riastrad /* 48 1.1 riastrad * Nothing to be placed after @simple, since size of @simple is 49 1.1 riastrad * unknown. 50 1.1 riastrad */ 51 1.1 riastrad }; 52 1.1 riastrad 53 1.1 riastrad 54 1.1 riastrad /** 55 1.1 riastrad * vmw_simple_resource_init - Initialize a simple resource object. 56 1.1 riastrad * 57 1.1 riastrad * @dev_priv: Pointer to a struct device private. 58 1.1 riastrad * @simple: The struct vmw_simple_resource to initialize. 59 1.1 riastrad * @data: Data passed to the information initialization function. 60 1.1 riastrad * @res_free: Function pointer to destroy the simple resource. 61 1.1 riastrad * 62 1.1 riastrad * Returns: 63 1.1 riastrad * 0 if succeeded. 64 1.1 riastrad * Negative error value if error, in which case the resource will have been 65 1.1 riastrad * freed. 66 1.1 riastrad */ 67 1.1 riastrad static int vmw_simple_resource_init(struct vmw_private *dev_priv, 68 1.1 riastrad struct vmw_simple_resource *simple, 69 1.1 riastrad void *data, 70 1.1 riastrad void (*res_free)(struct vmw_resource *res)) 71 1.1 riastrad { 72 1.1 riastrad struct vmw_resource *res = &simple->res; 73 1.1 riastrad int ret; 74 1.1 riastrad 75 1.1 riastrad ret = vmw_resource_init(dev_priv, res, false, res_free, 76 1.1 riastrad &simple->func->res_func); 77 1.1 riastrad 78 1.1 riastrad if (ret) { 79 1.1 riastrad res_free(res); 80 1.1 riastrad return ret; 81 1.1 riastrad } 82 1.1 riastrad 83 1.1 riastrad ret = simple->func->init(res, data); 84 1.1 riastrad if (ret) { 85 1.1 riastrad vmw_resource_unreference(&res); 86 1.1 riastrad return ret; 87 1.1 riastrad } 88 1.1 riastrad 89 1.1 riastrad simple->res.hw_destroy = simple->func->hw_destroy; 90 1.1 riastrad 91 1.1 riastrad return 0; 92 1.1 riastrad } 93 1.1 riastrad 94 1.1 riastrad /** 95 1.1 riastrad * vmw_simple_resource_free - Free a simple resource object. 96 1.1 riastrad * 97 1.1 riastrad * @res: The struct vmw_resource member of the simple resource object. 98 1.1 riastrad * 99 1.1 riastrad * Frees memory and memory accounting for the object. 100 1.1 riastrad */ 101 1.1 riastrad static void vmw_simple_resource_free(struct vmw_resource *res) 102 1.1 riastrad { 103 1.1 riastrad struct vmw_user_simple_resource *usimple = 104 1.1 riastrad container_of(res, struct vmw_user_simple_resource, 105 1.1 riastrad simple.res); 106 1.1 riastrad struct vmw_private *dev_priv = res->dev_priv; 107 1.1 riastrad size_t size = usimple->account_size; 108 1.1 riastrad 109 1.1 riastrad ttm_base_object_kfree(usimple, base); 110 1.1 riastrad ttm_mem_global_free(vmw_mem_glob(dev_priv), size); 111 1.1 riastrad } 112 1.1 riastrad 113 1.1 riastrad /** 114 1.1 riastrad * vmw_simple_resource_base_release - TTM object release callback 115 1.1 riastrad * 116 1.1 riastrad * @p_base: The struct ttm_base_object member of the simple resource object. 117 1.1 riastrad * 118 1.1 riastrad * Called when the last reference to the embedded struct ttm_base_object is 119 1.1 riastrad * gone. Typically results in an object free, unless there are other 120 1.1 riastrad * references to the embedded struct vmw_resource. 121 1.1 riastrad */ 122 1.1 riastrad static void vmw_simple_resource_base_release(struct ttm_base_object **p_base) 123 1.1 riastrad { 124 1.1 riastrad struct ttm_base_object *base = *p_base; 125 1.1 riastrad struct vmw_user_simple_resource *usimple = 126 1.1 riastrad container_of(base, struct vmw_user_simple_resource, base); 127 1.1 riastrad struct vmw_resource *res = &usimple->simple.res; 128 1.1 riastrad 129 1.1 riastrad *p_base = NULL; 130 1.1 riastrad vmw_resource_unreference(&res); 131 1.1 riastrad } 132 1.1 riastrad 133 1.1 riastrad /** 134 1.1 riastrad * vmw_simple_resource_create_ioctl - Helper to set up an ioctl function to 135 1.1 riastrad * create a struct vmw_simple_resource. 136 1.1 riastrad * 137 1.1 riastrad * @dev: Pointer to a struct drm device. 138 1.1 riastrad * @data: Ioctl argument. 139 1.1 riastrad * @file_priv: Pointer to a struct drm_file identifying the caller. 140 1.1 riastrad * @func: Pointer to a struct vmw_simple_resource_func identifying the 141 1.1 riastrad * simple resource type. 142 1.1 riastrad * 143 1.1 riastrad * Returns: 144 1.1 riastrad * 0 if success, 145 1.1 riastrad * Negative error value on error. 146 1.1 riastrad */ 147 1.1 riastrad int 148 1.1 riastrad vmw_simple_resource_create_ioctl(struct drm_device *dev, void *data, 149 1.1 riastrad struct drm_file *file_priv, 150 1.1 riastrad const struct vmw_simple_resource_func *func) 151 1.1 riastrad { 152 1.1 riastrad struct vmw_private *dev_priv = vmw_priv(dev); 153 1.1 riastrad struct vmw_user_simple_resource *usimple; 154 1.1 riastrad struct vmw_resource *res; 155 1.1 riastrad struct vmw_resource *tmp; 156 1.1 riastrad struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile; 157 1.1 riastrad struct ttm_operation_ctx ctx = { 158 1.1 riastrad .interruptible = true, 159 1.1 riastrad .no_wait_gpu = false 160 1.1 riastrad }; 161 1.1 riastrad size_t alloc_size; 162 1.1 riastrad size_t account_size; 163 1.1 riastrad int ret; 164 1.1 riastrad 165 1.1 riastrad alloc_size = offsetof(struct vmw_user_simple_resource, simple) + 166 1.1 riastrad func->size; 167 1.1 riastrad account_size = ttm_round_pot(alloc_size) + VMW_IDA_ACC_SIZE + 168 1.1 riastrad TTM_OBJ_EXTRA_SIZE; 169 1.1 riastrad 170 1.1 riastrad ret = ttm_read_lock(&dev_priv->reservation_sem, true); 171 1.1 riastrad if (ret) 172 1.1 riastrad return ret; 173 1.1 riastrad 174 1.1 riastrad ret = ttm_mem_global_alloc(vmw_mem_glob(dev_priv), account_size, 175 1.1 riastrad &ctx); 176 1.1 riastrad ttm_read_unlock(&dev_priv->reservation_sem); 177 1.1 riastrad if (ret) { 178 1.1 riastrad if (ret != -ERESTARTSYS) 179 1.1 riastrad DRM_ERROR("Out of graphics memory for %s" 180 1.1 riastrad " creation.\n", func->res_func.type_name); 181 1.1 riastrad 182 1.1 riastrad goto out_ret; 183 1.1 riastrad } 184 1.1 riastrad 185 1.1 riastrad usimple = kzalloc(alloc_size, GFP_KERNEL); 186 1.1 riastrad if (!usimple) { 187 1.1 riastrad ttm_mem_global_free(vmw_mem_glob(dev_priv), 188 1.1 riastrad account_size); 189 1.1 riastrad ret = -ENOMEM; 190 1.1 riastrad goto out_ret; 191 1.1 riastrad } 192 1.1 riastrad 193 1.1 riastrad usimple->simple.func = func; 194 1.1 riastrad usimple->account_size = account_size; 195 1.1 riastrad res = &usimple->simple.res; 196 1.1 riastrad usimple->base.shareable = false; 197 1.1 riastrad usimple->base.tfile = NULL; 198 1.1 riastrad 199 1.1 riastrad /* 200 1.1 riastrad * From here on, the destructor takes over resource freeing. 201 1.1 riastrad */ 202 1.1 riastrad ret = vmw_simple_resource_init(dev_priv, &usimple->simple, 203 1.1 riastrad data, vmw_simple_resource_free); 204 1.1 riastrad if (ret) 205 1.1 riastrad goto out_ret; 206 1.1 riastrad 207 1.1 riastrad tmp = vmw_resource_reference(res); 208 1.1 riastrad ret = ttm_base_object_init(tfile, &usimple->base, false, 209 1.1 riastrad func->ttm_res_type, 210 1.1 riastrad &vmw_simple_resource_base_release, NULL); 211 1.1 riastrad 212 1.1 riastrad if (ret) { 213 1.1 riastrad vmw_resource_unreference(&tmp); 214 1.1 riastrad goto out_err; 215 1.1 riastrad } 216 1.1 riastrad 217 1.1 riastrad func->set_arg_handle(data, usimple->base.handle); 218 1.1 riastrad out_err: 219 1.1 riastrad vmw_resource_unreference(&res); 220 1.1 riastrad out_ret: 221 1.1 riastrad return ret; 222 1.1 riastrad } 223 1.1 riastrad 224 1.1 riastrad /** 225 1.1 riastrad * vmw_simple_resource_lookup - Look up a simple resource from its user-space 226 1.1 riastrad * handle. 227 1.1 riastrad * 228 1.1 riastrad * @tfile: struct ttm_object_file identifying the caller. 229 1.1 riastrad * @handle: The user-space handle. 230 1.1 riastrad * @func: The struct vmw_simple_resource_func identifying the simple resource 231 1.1 riastrad * type. 232 1.1 riastrad * 233 1.1 riastrad * Returns: Refcounted pointer to the embedded struct vmw_resource if 234 1.1 riastrad * successfule. Error pointer otherwise. 235 1.1 riastrad */ 236 1.1 riastrad struct vmw_resource * 237 1.1 riastrad vmw_simple_resource_lookup(struct ttm_object_file *tfile, 238 1.1 riastrad uint32_t handle, 239 1.1 riastrad const struct vmw_simple_resource_func *func) 240 1.1 riastrad { 241 1.1 riastrad struct vmw_user_simple_resource *usimple; 242 1.1 riastrad struct ttm_base_object *base; 243 1.1 riastrad struct vmw_resource *res; 244 1.1 riastrad 245 1.1 riastrad base = ttm_base_object_lookup(tfile, handle); 246 1.1 riastrad if (!base) { 247 1.1 riastrad VMW_DEBUG_USER("Invalid %s handle 0x%08lx.\n", 248 1.1 riastrad func->res_func.type_name, 249 1.1 riastrad (unsigned long) handle); 250 1.1 riastrad return ERR_PTR(-ESRCH); 251 1.1 riastrad } 252 1.1 riastrad 253 1.1 riastrad if (ttm_base_object_type(base) != func->ttm_res_type) { 254 1.1 riastrad ttm_base_object_unref(&base); 255 1.1 riastrad VMW_DEBUG_USER("Invalid type of %s handle 0x%08lx.\n", 256 1.1 riastrad func->res_func.type_name, 257 1.1 riastrad (unsigned long) handle); 258 1.1 riastrad return ERR_PTR(-EINVAL); 259 1.1 riastrad } 260 1.1 riastrad 261 1.1 riastrad usimple = container_of(base, typeof(*usimple), base); 262 1.1 riastrad res = vmw_resource_reference(&usimple->simple.res); 263 1.1 riastrad ttm_base_object_unref(&base); 264 1.1 riastrad 265 1.1 riastrad return res; 266 1.1 riastrad } 267