Home | History | Annotate | Line # | Download | only in vmwgfx
      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