vmwgfx_resource.c revision 2f5993cca67f9c80dcd390feef13695ca072b8a5
1fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz/************************************************************************** 2fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * 3fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * Copyright © 2009 VMware, Inc., Palo Alto, CA., USA 4fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * All Rights Reserved. 5fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * 6fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * Permission is hereby granted, free of charge, to any person obtaining a 7fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * copy of this software and associated documentation files (the 8fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * "Software"), to deal in the Software without restriction, including 9fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * without limitation the rights to use, copy, modify, merge, publish, 10fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * distribute, sub license, and/or sell copies of the Software, and to 11fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * permit persons to whom the Software is furnished to do so, subject to 12fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * the following conditions: 13fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * 14fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * The above copyright notice and this permission notice (including the 15fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * next paragraph) shall be included in all copies or substantial portions 16fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * of the Software. 17fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * 18fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 21fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, 22fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 23fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 24fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * USE OR OTHER DEALINGS IN THE SOFTWARE. 25fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * 26fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz **************************************************************************/ 27fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 28fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz#include "vmwgfx_drv.h" 29fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz#include "vmwgfx_drm.h" 30fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz#include "ttm/ttm_object.h" 31fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz#include "ttm/ttm_placement.h" 32fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz#include "drmP.h" 33fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 34fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz#define VMW_RES_CONTEXT ttm_driver_type0 35fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz#define VMW_RES_SURFACE ttm_driver_type1 36fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz#define VMW_RES_STREAM ttm_driver_type2 37fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 38fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzstruct vmw_user_context { 39fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct ttm_base_object base; 40fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_resource res; 41fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz}; 42fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 43fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzstruct vmw_user_surface { 44fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct ttm_base_object base; 45fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_surface srf; 46fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz}; 47fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 48fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzstruct vmw_user_dma_buffer { 49fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct ttm_base_object base; 50fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_dma_buffer dma; 51fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz}; 52fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 53fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzstruct vmw_bo_user_rep { 54fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz uint32_t handle; 55fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz uint64_t map_handle; 56fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz}; 57fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 58fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzstruct vmw_stream { 59fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_resource res; 60fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz uint32_t stream_id; 61fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz}; 62fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 63fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzstruct vmw_user_stream { 64fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct ttm_base_object base; 65fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_stream stream; 66fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz}; 67fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 68fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzstatic inline struct vmw_dma_buffer * 69fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzvmw_dma_buffer(struct ttm_buffer_object *bo) 70fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 71fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return container_of(bo, struct vmw_dma_buffer, base); 72fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 73fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 74fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzstatic inline struct vmw_user_dma_buffer * 75fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzvmw_user_dma_buffer(struct ttm_buffer_object *bo) 76fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 77fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_dma_buffer *vmw_bo = vmw_dma_buffer(bo); 78fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return container_of(vmw_bo, struct vmw_user_dma_buffer, dma); 79fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 80fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 81fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzstruct vmw_resource *vmw_resource_reference(struct vmw_resource *res) 82fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 83fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz kref_get(&res->kref); 84fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return res; 85fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 86fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 87fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzstatic void vmw_resource_release(struct kref *kref) 88fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 89fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_resource *res = 90fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz container_of(kref, struct vmw_resource, kref); 91fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_private *dev_priv = res->dev_priv; 92fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 93fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz idr_remove(res->idr, res->id); 94fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz write_unlock(&dev_priv->resource_lock); 95fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 96fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (likely(res->hw_destroy != NULL)) 97fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz res->hw_destroy(res); 98fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 99fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (res->res_free != NULL) 100fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz res->res_free(res); 101fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz else 102fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz kfree(res); 103fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 104fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz write_lock(&dev_priv->resource_lock); 105fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 106fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 107fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzvoid vmw_resource_unreference(struct vmw_resource **p_res) 108fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 109fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_resource *res = *p_res; 110fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_private *dev_priv = res->dev_priv; 111fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 112fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz *p_res = NULL; 113fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz write_lock(&dev_priv->resource_lock); 114fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz kref_put(&res->kref, vmw_resource_release); 115fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz write_unlock(&dev_priv->resource_lock); 116fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 117fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 118fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzstatic int vmw_resource_init(struct vmw_private *dev_priv, 119fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_resource *res, 120fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct idr *idr, 121fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz enum ttm_object_type obj_type, 122fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz void (*res_free) (struct vmw_resource *res)) 123fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 124fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz int ret; 125fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 126fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz kref_init(&res->kref); 127fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz res->hw_destroy = NULL; 128fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz res->res_free = res_free; 129fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz res->res_type = obj_type; 130fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz res->idr = idr; 131fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz res->avail = false; 132fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz res->dev_priv = dev_priv; 133fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 134fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz do { 135fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (unlikely(idr_pre_get(idr, GFP_KERNEL) == 0)) 136fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return -ENOMEM; 137fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 138fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz write_lock(&dev_priv->resource_lock); 139fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ret = idr_get_new_above(idr, res, 1, &res->id); 140fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz write_unlock(&dev_priv->resource_lock); 141fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 142fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz } while (ret == -EAGAIN); 143fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 144fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return ret; 145fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 146fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 147fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz/** 148fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * vmw_resource_activate 149fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * 150fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * @res: Pointer to the newly created resource 151fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * @hw_destroy: Destroy function. NULL if none. 152fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * 153fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * Activate a resource after the hardware has been made aware of it. 154fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * Set tye destroy function to @destroy. Typically this frees the 155fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * resource and destroys the hardware resources associated with it. 156fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * Activate basically means that the function vmw_resource_lookup will 157fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * find it. 158fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz */ 159fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 160fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzstatic void vmw_resource_activate(struct vmw_resource *res, 161fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz void (*hw_destroy) (struct vmw_resource *)) 162fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 163fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_private *dev_priv = res->dev_priv; 164fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 165fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz write_lock(&dev_priv->resource_lock); 166fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz res->avail = true; 167fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz res->hw_destroy = hw_destroy; 168fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz write_unlock(&dev_priv->resource_lock); 169fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 170fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 171fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzstruct vmw_resource *vmw_resource_lookup(struct vmw_private *dev_priv, 172fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct idr *idr, int id) 173fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 174fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_resource *res; 175fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 176fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz read_lock(&dev_priv->resource_lock); 177fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz res = idr_find(idr, id); 178fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (res && res->avail) 179fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz kref_get(&res->kref); 180fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz else 181fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz res = NULL; 182fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz read_unlock(&dev_priv->resource_lock); 183fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 184fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (unlikely(res == NULL)) 185fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return NULL; 186fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 187fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return res; 188fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 189fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 190fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz/** 191fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * Context management: 192fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz */ 193fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 194fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzstatic void vmw_hw_context_destroy(struct vmw_resource *res) 195fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 196fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 197fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_private *dev_priv = res->dev_priv; 198fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct { 199fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz SVGA3dCmdHeader header; 200fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz SVGA3dCmdDestroyContext body; 201fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz } *cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd)); 202fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 203fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (unlikely(cmd == NULL)) { 204fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz DRM_ERROR("Failed reserving FIFO space for surface " 205fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz "destruction.\n"); 206fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return; 207fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz } 208fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 209fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz cmd->header.id = cpu_to_le32(SVGA_3D_CMD_CONTEXT_DESTROY); 210fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz cmd->header.size = cpu_to_le32(sizeof(cmd->body)); 211fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz cmd->body.cid = cpu_to_le32(res->id); 212fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 213fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz vmw_fifo_commit(dev_priv, sizeof(*cmd)); 21430c78bb838b26ec7997515844c0c734e454b3cbaThomas Hellstrom vmw_3d_resource_dec(dev_priv); 215fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 216fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 217fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzstatic int vmw_context_init(struct vmw_private *dev_priv, 218fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_resource *res, 219fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz void (*res_free) (struct vmw_resource *res)) 220fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 221fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz int ret; 222fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 223fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct { 224fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz SVGA3dCmdHeader header; 225fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz SVGA3dCmdDefineContext body; 226fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz } *cmd; 227fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 228fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ret = vmw_resource_init(dev_priv, res, &dev_priv->context_idr, 229fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz VMW_RES_CONTEXT, res_free); 230fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 231fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (unlikely(ret != 0)) { 232fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (res_free == NULL) 233fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz kfree(res); 234fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz else 235fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz res_free(res); 236fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return ret; 237fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz } 238fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 239fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd)); 240fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (unlikely(cmd == NULL)) { 241fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz DRM_ERROR("Fifo reserve failed.\n"); 242fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz vmw_resource_unreference(&res); 243fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return -ENOMEM; 244fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz } 245fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 246fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz cmd->header.id = cpu_to_le32(SVGA_3D_CMD_CONTEXT_DEFINE); 247fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz cmd->header.size = cpu_to_le32(sizeof(cmd->body)); 248fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz cmd->body.cid = cpu_to_le32(res->id); 249fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 250fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz vmw_fifo_commit(dev_priv, sizeof(*cmd)); 25130c78bb838b26ec7997515844c0c734e454b3cbaThomas Hellstrom (void) vmw_3d_resource_inc(dev_priv); 252fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz vmw_resource_activate(res, vmw_hw_context_destroy); 253fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return 0; 254fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 255fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 256fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzstruct vmw_resource *vmw_context_alloc(struct vmw_private *dev_priv) 257fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 258fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_resource *res = kmalloc(sizeof(*res), GFP_KERNEL); 259fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz int ret; 260fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 261fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (unlikely(res == NULL)) 262fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return NULL; 263fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 264fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ret = vmw_context_init(dev_priv, res, NULL); 265fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return (ret == 0) ? res : NULL; 266fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 267fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 268fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz/** 269fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * User-space context management: 270fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz */ 271fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 272fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzstatic void vmw_user_context_free(struct vmw_resource *res) 273fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 274fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_user_context *ctx = 275fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz container_of(res, struct vmw_user_context, res); 276fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 277fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz kfree(ctx); 278fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 279fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 280fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz/** 281fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * This function is called when user space has no more references on the 282fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * base object. It releases the base-object's reference on the resource object. 283fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz */ 284fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 285fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzstatic void vmw_user_context_base_release(struct ttm_base_object **p_base) 286fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 287fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct ttm_base_object *base = *p_base; 288fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_user_context *ctx = 289fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz container_of(base, struct vmw_user_context, base); 290fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_resource *res = &ctx->res; 291fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 292fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz *p_base = NULL; 293fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz vmw_resource_unreference(&res); 294fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 295fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 296fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzint vmw_context_destroy_ioctl(struct drm_device *dev, void *data, 297fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct drm_file *file_priv) 298fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 299fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_private *dev_priv = vmw_priv(dev); 300fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_resource *res; 301fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_user_context *ctx; 302fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct drm_vmw_context_arg *arg = (struct drm_vmw_context_arg *)data; 303fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile; 304fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz int ret = 0; 305fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 306fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz res = vmw_resource_lookup(dev_priv, &dev_priv->context_idr, arg->cid); 307fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (unlikely(res == NULL)) 308fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return -EINVAL; 309fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 310fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (res->res_free != &vmw_user_context_free) { 311fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ret = -EINVAL; 312fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz goto out; 313fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz } 314fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 315fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ctx = container_of(res, struct vmw_user_context, res); 316fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (ctx->base.tfile != tfile && !ctx->base.shareable) { 317fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ret = -EPERM; 318fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz goto out; 319fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz } 320fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 321fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ttm_ref_object_base_unref(tfile, ctx->base.hash.key, TTM_REF_USAGE); 322fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzout: 323fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz vmw_resource_unreference(&res); 324fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return ret; 325fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 326fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 327fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzint vmw_context_define_ioctl(struct drm_device *dev, void *data, 328fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct drm_file *file_priv) 329fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 330fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_private *dev_priv = vmw_priv(dev); 331fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_user_context *ctx = kmalloc(sizeof(*ctx), GFP_KERNEL); 332fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_resource *res; 333fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_resource *tmp; 334fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct drm_vmw_context_arg *arg = (struct drm_vmw_context_arg *)data; 335fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile; 336fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz int ret; 337fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 338fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (unlikely(ctx == NULL)) 339fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return -ENOMEM; 340fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 341fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz res = &ctx->res; 342fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ctx->base.shareable = false; 343fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ctx->base.tfile = NULL; 344fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 345fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ret = vmw_context_init(dev_priv, res, vmw_user_context_free); 346fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (unlikely(ret != 0)) 347fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return ret; 348fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 349fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz tmp = vmw_resource_reference(&ctx->res); 350fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ret = ttm_base_object_init(tfile, &ctx->base, false, VMW_RES_CONTEXT, 351fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz &vmw_user_context_base_release, NULL); 352fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 353fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (unlikely(ret != 0)) { 354fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz vmw_resource_unreference(&tmp); 355fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz goto out_err; 356fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz } 357fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 358fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz arg->cid = res->id; 359fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzout_err: 360fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz vmw_resource_unreference(&res); 361fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return ret; 362fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 363fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 364fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 365fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzint vmw_context_check(struct vmw_private *dev_priv, 366fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct ttm_object_file *tfile, 367fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz int id) 368fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 369fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_resource *res; 370fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz int ret = 0; 371fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 372fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz read_lock(&dev_priv->resource_lock); 373fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz res = idr_find(&dev_priv->context_idr, id); 374fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (res && res->avail) { 375fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_user_context *ctx = 376fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz container_of(res, struct vmw_user_context, res); 377fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (ctx->base.tfile != tfile && !ctx->base.shareable) 378fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ret = -EPERM; 379fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz } else 380fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ret = -EINVAL; 381fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz read_unlock(&dev_priv->resource_lock); 382fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 383fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return ret; 384fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 385fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 386fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 387fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz/** 388fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * Surface management. 389fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz */ 390fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 391fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzstatic void vmw_hw_surface_destroy(struct vmw_resource *res) 392fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 393fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 394fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_private *dev_priv = res->dev_priv; 395fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct { 396fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz SVGA3dCmdHeader header; 397fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz SVGA3dCmdDestroySurface body; 398fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz } *cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd)); 399fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 400fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (unlikely(cmd == NULL)) { 401fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz DRM_ERROR("Failed reserving FIFO space for surface " 402fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz "destruction.\n"); 403fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return; 404fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz } 405fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 406fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz cmd->header.id = cpu_to_le32(SVGA_3D_CMD_SURFACE_DESTROY); 407fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz cmd->header.size = cpu_to_le32(sizeof(cmd->body)); 408fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz cmd->body.sid = cpu_to_le32(res->id); 409fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 410fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz vmw_fifo_commit(dev_priv, sizeof(*cmd)); 41130c78bb838b26ec7997515844c0c734e454b3cbaThomas Hellstrom vmw_3d_resource_dec(dev_priv); 412fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 413fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 414fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzvoid vmw_surface_res_free(struct vmw_resource *res) 415fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 416fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_surface *srf = container_of(res, struct vmw_surface, res); 417fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 418fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz kfree(srf->sizes); 419fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz kfree(srf->snooper.image); 420fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz kfree(srf); 421fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 422fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 423fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzint vmw_surface_init(struct vmw_private *dev_priv, 424fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_surface *srf, 425fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz void (*res_free) (struct vmw_resource *res)) 426fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 427fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz int ret; 428fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct { 429fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz SVGA3dCmdHeader header; 430fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz SVGA3dCmdDefineSurface body; 431fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz } *cmd; 432fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz SVGA3dSize *cmd_size; 433fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_resource *res = &srf->res; 434fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct drm_vmw_size *src_size; 435fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz size_t submit_size; 436fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz uint32_t cmd_len; 437fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz int i; 438fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 439fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz BUG_ON(res_free == NULL); 440fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ret = vmw_resource_init(dev_priv, res, &dev_priv->surface_idr, 441fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz VMW_RES_SURFACE, res_free); 442fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 443fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (unlikely(ret != 0)) { 444fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz res_free(res); 445fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return ret; 446fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz } 447fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 448fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz submit_size = sizeof(*cmd) + srf->num_sizes * sizeof(SVGA3dSize); 449fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz cmd_len = sizeof(cmd->body) + srf->num_sizes * sizeof(SVGA3dSize); 450fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 451fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz cmd = vmw_fifo_reserve(dev_priv, submit_size); 452fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (unlikely(cmd == NULL)) { 453fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz DRM_ERROR("Fifo reserve failed for create surface.\n"); 454fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz vmw_resource_unreference(&res); 455fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return -ENOMEM; 456fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz } 457fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 458fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz cmd->header.id = cpu_to_le32(SVGA_3D_CMD_SURFACE_DEFINE); 459fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz cmd->header.size = cpu_to_le32(cmd_len); 460fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz cmd->body.sid = cpu_to_le32(res->id); 461fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz cmd->body.surfaceFlags = cpu_to_le32(srf->flags); 462fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz cmd->body.format = cpu_to_le32(srf->format); 463fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz for (i = 0; i < DRM_VMW_MAX_SURFACE_FACES; ++i) { 464fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz cmd->body.face[i].numMipLevels = 465fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz cpu_to_le32(srf->mip_levels[i]); 466fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz } 467fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 468fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz cmd += 1; 469fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz cmd_size = (SVGA3dSize *) cmd; 470fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz src_size = srf->sizes; 471fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 472fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz for (i = 0; i < srf->num_sizes; ++i, cmd_size++, src_size++) { 473fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz cmd_size->width = cpu_to_le32(src_size->width); 474fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz cmd_size->height = cpu_to_le32(src_size->height); 475fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz cmd_size->depth = cpu_to_le32(src_size->depth); 476fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz } 477fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 478fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz vmw_fifo_commit(dev_priv, submit_size); 47930c78bb838b26ec7997515844c0c734e454b3cbaThomas Hellstrom (void) vmw_3d_resource_inc(dev_priv); 480fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz vmw_resource_activate(res, vmw_hw_surface_destroy); 481fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return 0; 482fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 483fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 484fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzstatic void vmw_user_surface_free(struct vmw_resource *res) 485fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 486fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_surface *srf = container_of(res, struct vmw_surface, res); 487fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_user_surface *user_srf = 488fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz container_of(srf, struct vmw_user_surface, srf); 489fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 490fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz kfree(srf->sizes); 491fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz kfree(srf->snooper.image); 492fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz kfree(user_srf); 493fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 494fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 4957a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstromint vmw_user_surface_lookup_handle(struct vmw_private *dev_priv, 4967a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom struct ttm_object_file *tfile, 4977a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom uint32_t handle, struct vmw_surface **out) 498fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 499fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_resource *res; 500fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_surface *srf; 501fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_user_surface *user_srf; 5027a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom struct ttm_base_object *base; 5037a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom int ret = -EINVAL; 504fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 5057a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom base = ttm_base_object_lookup(tfile, handle); 5067a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom if (unlikely(base == NULL)) 507fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return -EINVAL; 508fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 5097a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom if (unlikely(base->object_type != VMW_RES_SURFACE)) 5107a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom goto out_bad_resource; 5117a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom 5127a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom user_srf = container_of(base, struct vmw_user_surface, base); 5137a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom srf = &user_srf->srf; 5147a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom res = &srf->res; 5157a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom 5167a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom read_lock(&dev_priv->resource_lock); 5177a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom 5187a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom if (!res->avail || res->res_free != &vmw_user_surface_free) { 5197a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom read_unlock(&dev_priv->resource_lock); 5207a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom goto out_bad_resource; 5217a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom } 522fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 5237a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom kref_get(&res->kref); 5247a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom read_unlock(&dev_priv->resource_lock); 525fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 526fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz *out = srf; 5277a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom ret = 0; 5287a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom 5297a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstromout_bad_resource: 5307a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom ttm_base_object_unref(&base); 5317a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom 5327a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom return ret; 533fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 534fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 535fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzstatic void vmw_user_surface_base_release(struct ttm_base_object **p_base) 536fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 537fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct ttm_base_object *base = *p_base; 538fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_user_surface *user_srf = 539fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz container_of(base, struct vmw_user_surface, base); 540fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_resource *res = &user_srf->srf.res; 541fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 542fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz *p_base = NULL; 543fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz vmw_resource_unreference(&res); 544fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 545fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 546fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzint vmw_surface_destroy_ioctl(struct drm_device *dev, void *data, 547fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct drm_file *file_priv) 548fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 549fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct drm_vmw_surface_arg *arg = (struct drm_vmw_surface_arg *)data; 550fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile; 551fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 5527a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom return ttm_ref_object_base_unref(tfile, arg->sid, TTM_REF_USAGE); 553fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 554fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 555fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzint vmw_surface_define_ioctl(struct drm_device *dev, void *data, 556fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct drm_file *file_priv) 557fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 558fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_private *dev_priv = vmw_priv(dev); 559fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_user_surface *user_srf = 560fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz kmalloc(sizeof(*user_srf), GFP_KERNEL); 561fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_surface *srf; 562fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_resource *res; 563fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_resource *tmp; 564fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz union drm_vmw_surface_create_arg *arg = 565fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz (union drm_vmw_surface_create_arg *)data; 566fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct drm_vmw_surface_create_req *req = &arg->req; 567fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct drm_vmw_surface_arg *rep = &arg->rep; 568fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile; 569fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct drm_vmw_size __user *user_sizes; 570fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz int ret; 571fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz int i; 572fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 573fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (unlikely(user_srf == NULL)) 574fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return -ENOMEM; 575fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 576fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz srf = &user_srf->srf; 577fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz res = &srf->res; 578fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 579fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz srf->flags = req->flags; 580fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz srf->format = req->format; 581a87897edbae2d60db7bcb6bb0a75e82013d68305Jakob Bornecrantz srf->scanout = req->scanout; 582fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz memcpy(srf->mip_levels, req->mip_levels, sizeof(srf->mip_levels)); 583fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz srf->num_sizes = 0; 584fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz for (i = 0; i < DRM_VMW_MAX_SURFACE_FACES; ++i) 585fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz srf->num_sizes += srf->mip_levels[i]; 586fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 587fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (srf->num_sizes > DRM_VMW_MAX_SURFACE_FACES * 588fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz DRM_VMW_MAX_MIP_LEVELS) { 589fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ret = -EINVAL; 590fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz goto out_err0; 591fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz } 592fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 593fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz srf->sizes = kmalloc(srf->num_sizes * sizeof(*srf->sizes), GFP_KERNEL); 594fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (unlikely(srf->sizes == NULL)) { 595fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ret = -ENOMEM; 596fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz goto out_err0; 597fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz } 598fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 599fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz user_sizes = (struct drm_vmw_size __user *)(unsigned long) 600fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz req->size_addr; 601fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 602fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ret = copy_from_user(srf->sizes, user_sizes, 603fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz srf->num_sizes * sizeof(*srf->sizes)); 6049b8eb4d14767209c83087063352cd04266ecdfd1Dan Carpenter if (unlikely(ret != 0)) { 6059b8eb4d14767209c83087063352cd04266ecdfd1Dan Carpenter ret = -EFAULT; 606fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz goto out_err1; 6079b8eb4d14767209c83087063352cd04266ecdfd1Dan Carpenter } 608fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 6095ffdb658f605cbc420944e7c7eeec9fbb8a73772Jakob Bornecrantz if (srf->scanout && 61050ec3b7c35fda131e92abc6f9d93a230b7e009ebThomas Hellstrom srf->num_sizes == 1 && 61150ec3b7c35fda131e92abc6f9d93a230b7e009ebThomas Hellstrom srf->sizes[0].width == 64 && 61250ec3b7c35fda131e92abc6f9d93a230b7e009ebThomas Hellstrom srf->sizes[0].height == 64 && 61350ec3b7c35fda131e92abc6f9d93a230b7e009ebThomas Hellstrom srf->format == SVGA3D_A8R8G8B8) { 61450ec3b7c35fda131e92abc6f9d93a230b7e009ebThomas Hellstrom 61550ec3b7c35fda131e92abc6f9d93a230b7e009ebThomas Hellstrom srf->snooper.image = kmalloc(64 * 64 * 4, GFP_KERNEL); 61650ec3b7c35fda131e92abc6f9d93a230b7e009ebThomas Hellstrom /* clear the image */ 61750ec3b7c35fda131e92abc6f9d93a230b7e009ebThomas Hellstrom if (srf->snooper.image) { 61850ec3b7c35fda131e92abc6f9d93a230b7e009ebThomas Hellstrom memset(srf->snooper.image, 0x00, 64 * 64 * 4); 61950ec3b7c35fda131e92abc6f9d93a230b7e009ebThomas Hellstrom } else { 62050ec3b7c35fda131e92abc6f9d93a230b7e009ebThomas Hellstrom DRM_ERROR("Failed to allocate cursor_image\n"); 62150ec3b7c35fda131e92abc6f9d93a230b7e009ebThomas Hellstrom ret = -ENOMEM; 62250ec3b7c35fda131e92abc6f9d93a230b7e009ebThomas Hellstrom goto out_err1; 62350ec3b7c35fda131e92abc6f9d93a230b7e009ebThomas Hellstrom } 62450ec3b7c35fda131e92abc6f9d93a230b7e009ebThomas Hellstrom } else { 62550ec3b7c35fda131e92abc6f9d93a230b7e009ebThomas Hellstrom srf->snooper.image = NULL; 62650ec3b7c35fda131e92abc6f9d93a230b7e009ebThomas Hellstrom } 62750ec3b7c35fda131e92abc6f9d93a230b7e009ebThomas Hellstrom srf->snooper.crtc = NULL; 62850ec3b7c35fda131e92abc6f9d93a230b7e009ebThomas Hellstrom 629fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz user_srf->base.shareable = false; 630fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz user_srf->base.tfile = NULL; 631fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 632fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz /** 633fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * From this point, the generic resource management functions 634fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * destroy the object on failure. 635fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz */ 636fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 637fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ret = vmw_surface_init(dev_priv, srf, vmw_user_surface_free); 638fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (unlikely(ret != 0)) 639fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return ret; 640fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 641fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz tmp = vmw_resource_reference(&srf->res); 642fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ret = ttm_base_object_init(tfile, &user_srf->base, 643fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz req->shareable, VMW_RES_SURFACE, 644fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz &vmw_user_surface_base_release, NULL); 645fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 646fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (unlikely(ret != 0)) { 647fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz vmw_resource_unreference(&tmp); 648fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz vmw_resource_unreference(&res); 649fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return ret; 650fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz } 651fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 6527a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom rep->sid = user_srf->base.hash.key; 6537a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom if (rep->sid == SVGA3D_INVALID_ID) 6547a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom DRM_ERROR("Created bad Surface ID.\n"); 6557a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom 656fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz vmw_resource_unreference(&res); 657fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return 0; 658fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzout_err1: 659fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz kfree(srf->sizes); 660fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzout_err0: 661fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz kfree(user_srf); 662fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return ret; 663fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 664fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 665fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzint vmw_surface_reference_ioctl(struct drm_device *dev, void *data, 666fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct drm_file *file_priv) 667fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 668fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz union drm_vmw_surface_reference_arg *arg = 669fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz (union drm_vmw_surface_reference_arg *)data; 670fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct drm_vmw_surface_arg *req = &arg->req; 671fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct drm_vmw_surface_create_req *rep = &arg->rep; 672fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile; 673fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_surface *srf; 674fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_user_surface *user_srf; 675fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct drm_vmw_size __user *user_sizes; 6767a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom struct ttm_base_object *base; 6777a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom int ret = -EINVAL; 678fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 6797a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom base = ttm_base_object_lookup(tfile, req->sid); 6807a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom if (unlikely(base == NULL)) { 6817a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom DRM_ERROR("Could not find surface to reference.\n"); 682fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return -EINVAL; 683fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz } 684fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 6857a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom if (unlikely(base->object_type != VMW_RES_SURFACE)) 6867a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom goto out_bad_resource; 6877a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom 6887a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom user_srf = container_of(base, struct vmw_user_surface, base); 6897a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom srf = &user_srf->srf; 690fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 691fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ret = ttm_ref_object_add(tfile, &user_srf->base, TTM_REF_USAGE, NULL); 692fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (unlikely(ret != 0)) { 693fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz DRM_ERROR("Could not add a reference to a surface.\n"); 6947a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom goto out_no_reference; 695fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz } 696fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 697fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz rep->flags = srf->flags; 698fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz rep->format = srf->format; 699fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz memcpy(rep->mip_levels, srf->mip_levels, sizeof(srf->mip_levels)); 700fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz user_sizes = (struct drm_vmw_size __user *)(unsigned long) 701fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz rep->size_addr; 702fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 703fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (user_sizes) 704fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ret = copy_to_user(user_sizes, srf->sizes, 705fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz srf->num_sizes * sizeof(*srf->sizes)); 7069b8eb4d14767209c83087063352cd04266ecdfd1Dan Carpenter if (unlikely(ret != 0)) { 707fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz DRM_ERROR("copy_to_user failed %p %u\n", 708fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz user_sizes, srf->num_sizes); 7099b8eb4d14767209c83087063352cd04266ecdfd1Dan Carpenter ret = -EFAULT; 7109b8eb4d14767209c83087063352cd04266ecdfd1Dan Carpenter } 7117a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstromout_bad_resource: 7127a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstromout_no_reference: 7137a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom ttm_base_object_unref(&base); 7147a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom 715fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return ret; 716fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 717fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 718fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzint vmw_surface_check(struct vmw_private *dev_priv, 719fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct ttm_object_file *tfile, 7207a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom uint32_t handle, int *id) 721fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 7227a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom struct ttm_base_object *base; 7237a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom struct vmw_user_surface *user_srf; 724fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 7257a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom int ret = -EPERM; 726fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 7277a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom base = ttm_base_object_lookup(tfile, handle); 7287a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom if (unlikely(base == NULL)) 7297a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom return -EINVAL; 7307a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom 7317a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom if (unlikely(base->object_type != VMW_RES_SURFACE)) 7327a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom goto out_bad_surface; 7337a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom 7347a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom user_srf = container_of(base, struct vmw_user_surface, base); 7357a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom *id = user_srf->srf.res.id; 7367a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom ret = 0; 7377a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom 7387a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstromout_bad_surface: 7397a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom /** 7407a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom * FIXME: May deadlock here when called from the 7417a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom * command parsing code. 7427a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom */ 743fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 7447a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom ttm_base_object_unref(&base); 745fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return ret; 746fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 747fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 748fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz/** 749fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * Buffer management. 750fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz */ 751fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 752fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzstatic size_t vmw_dmabuf_acc_size(struct ttm_bo_global *glob, 753fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz unsigned long num_pages) 754fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 755fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz static size_t bo_user_size = ~0; 756fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 757fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz size_t page_array_size = 758fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz (num_pages * sizeof(void *) + PAGE_SIZE - 1) & PAGE_MASK; 759fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 760fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (unlikely(bo_user_size == ~0)) { 761fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz bo_user_size = glob->ttm_bo_extra_size + 762fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ttm_round_pot(sizeof(struct vmw_dma_buffer)); 763fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz } 764fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 765fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return bo_user_size + page_array_size; 766fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 767fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 768effe1105bef07f42366c20eac41b80ff9fcf675eThomas Hellstromvoid vmw_dmabuf_bo_free(struct ttm_buffer_object *bo) 769effe1105bef07f42366c20eac41b80ff9fcf675eThomas Hellstrom{ 770effe1105bef07f42366c20eac41b80ff9fcf675eThomas Hellstrom struct vmw_dma_buffer *vmw_bo = vmw_dma_buffer(bo); 771effe1105bef07f42366c20eac41b80ff9fcf675eThomas Hellstrom struct ttm_bo_global *glob = bo->glob; 772effe1105bef07f42366c20eac41b80ff9fcf675eThomas Hellstrom 773effe1105bef07f42366c20eac41b80ff9fcf675eThomas Hellstrom ttm_mem_global_free(glob->mem_glob, bo->acc_size); 774fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz kfree(vmw_bo); 775fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 776fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 777fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzint vmw_dmabuf_init(struct vmw_private *dev_priv, 778fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_dma_buffer *vmw_bo, 779fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz size_t size, struct ttm_placement *placement, 780fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz bool interruptible, 781fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz void (*bo_free) (struct ttm_buffer_object *bo)) 782fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 783fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct ttm_bo_device *bdev = &dev_priv->bdev; 784fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct ttm_mem_global *mem_glob = bdev->glob->mem_glob; 785fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz size_t acc_size; 786fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz int ret; 787fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 788fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz BUG_ON(!bo_free); 789fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 790fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz acc_size = 791fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz vmw_dmabuf_acc_size(bdev->glob, 792fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz (size + PAGE_SIZE - 1) >> PAGE_SHIFT); 793fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 794fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ret = ttm_mem_global_alloc(mem_glob, acc_size, false, false); 795fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (unlikely(ret != 0)) { 796fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz /* we must free the bo here as 797fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * ttm_buffer_object_init does so as well */ 798fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz bo_free(&vmw_bo->base); 799fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return ret; 800fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz } 801fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 802fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz memset(vmw_bo, 0, sizeof(*vmw_bo)); 803fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 804fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz INIT_LIST_HEAD(&vmw_bo->validate_list); 805fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 806fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ret = ttm_bo_init(bdev, &vmw_bo->base, size, 807fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ttm_bo_type_device, placement, 808fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 0, 0, interruptible, 809fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz NULL, acc_size, bo_free); 810fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return ret; 811fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 812fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 813fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzstatic void vmw_user_dmabuf_destroy(struct ttm_buffer_object *bo) 814fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 815fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_user_dma_buffer *vmw_user_bo = vmw_user_dma_buffer(bo); 816fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct ttm_bo_global *glob = bo->glob; 817fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 818fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ttm_mem_global_free(glob->mem_glob, bo->acc_size); 819fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz kfree(vmw_user_bo); 820fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 821fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 822fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzstatic void vmw_user_dmabuf_release(struct ttm_base_object **p_base) 823fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 824fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_user_dma_buffer *vmw_user_bo; 825fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct ttm_base_object *base = *p_base; 826fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct ttm_buffer_object *bo; 827fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 828fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz *p_base = NULL; 829fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 830fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (unlikely(base == NULL)) 831fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return; 832fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 833fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz vmw_user_bo = container_of(base, struct vmw_user_dma_buffer, base); 834fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz bo = &vmw_user_bo->dma.base; 835fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ttm_bo_unref(&bo); 836fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 837fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 838fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzint vmw_dmabuf_alloc_ioctl(struct drm_device *dev, void *data, 839fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct drm_file *file_priv) 840fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 841fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_private *dev_priv = vmw_priv(dev); 842fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz union drm_vmw_alloc_dmabuf_arg *arg = 843fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz (union drm_vmw_alloc_dmabuf_arg *)data; 844fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct drm_vmw_alloc_dmabuf_req *req = &arg->req; 845fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct drm_vmw_dmabuf_rep *rep = &arg->rep; 846fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_user_dma_buffer *vmw_user_bo; 847fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct ttm_buffer_object *tmp; 848fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_master *vmaster = vmw_master(file_priv->master); 849fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz int ret; 850fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 851fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz vmw_user_bo = kzalloc(sizeof(*vmw_user_bo), GFP_KERNEL); 852fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (unlikely(vmw_user_bo == NULL)) 853fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return -ENOMEM; 854fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 855fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ret = ttm_read_lock(&vmaster->lock, true); 856fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (unlikely(ret != 0)) { 857fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz kfree(vmw_user_bo); 858fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return ret; 859fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz } 860fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 861fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ret = vmw_dmabuf_init(dev_priv, &vmw_user_bo->dma, req->size, 8628ba5152a3acd5914cade42a1c8c9dc58ad8d1a89Thomas Hellstrom &vmw_vram_sys_placement, true, 863fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz &vmw_user_dmabuf_destroy); 864fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (unlikely(ret != 0)) 8652f5993cca67f9c80dcd390feef13695ca072b8a5Thomas Hellstrom goto out_no_dmabuf; 866fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 867fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz tmp = ttm_bo_reference(&vmw_user_bo->dma.base); 868fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ret = ttm_base_object_init(vmw_fpriv(file_priv)->tfile, 869fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz &vmw_user_bo->base, 870fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz false, 871fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ttm_buffer_type, 872fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz &vmw_user_dmabuf_release, NULL); 8732f5993cca67f9c80dcd390feef13695ca072b8a5Thomas Hellstrom if (unlikely(ret != 0)) 8742f5993cca67f9c80dcd390feef13695ca072b8a5Thomas Hellstrom goto out_no_base_object; 8752f5993cca67f9c80dcd390feef13695ca072b8a5Thomas Hellstrom else { 876fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz rep->handle = vmw_user_bo->base.hash.key; 877fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz rep->map_handle = vmw_user_bo->dma.base.addr_space_offset; 878fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz rep->cur_gmr_id = vmw_user_bo->base.hash.key; 879fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz rep->cur_gmr_offset = 0; 880fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz } 881fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 8822f5993cca67f9c80dcd390feef13695ca072b8a5Thomas Hellstromout_no_base_object: 8832f5993cca67f9c80dcd390feef13695ca072b8a5Thomas Hellstrom ttm_bo_unref(&tmp); 8842f5993cca67f9c80dcd390feef13695ca072b8a5Thomas Hellstromout_no_dmabuf: 885fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ttm_read_unlock(&vmaster->lock); 886fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 8872f5993cca67f9c80dcd390feef13695ca072b8a5Thomas Hellstrom return ret; 888fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 889fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 890fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzint vmw_dmabuf_unref_ioctl(struct drm_device *dev, void *data, 891fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct drm_file *file_priv) 892fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 893fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct drm_vmw_unref_dmabuf_arg *arg = 894fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz (struct drm_vmw_unref_dmabuf_arg *)data; 895fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 896fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return ttm_ref_object_base_unref(vmw_fpriv(file_priv)->tfile, 897fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz arg->handle, 898fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz TTM_REF_USAGE); 899fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 900fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 901fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzuint32_t vmw_dmabuf_validate_node(struct ttm_buffer_object *bo, 902fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz uint32_t cur_validate_node) 903fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 904fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_dma_buffer *vmw_bo = vmw_dma_buffer(bo); 905fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 906fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (likely(vmw_bo->on_validate_list)) 907fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return vmw_bo->cur_validate_node; 908fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 909fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz vmw_bo->cur_validate_node = cur_validate_node; 910fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz vmw_bo->on_validate_list = true; 911fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 912fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return cur_validate_node; 913fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 914fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 915fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzvoid vmw_dmabuf_validate_clear(struct ttm_buffer_object *bo) 916fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 917fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_dma_buffer *vmw_bo = vmw_dma_buffer(bo); 918fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 919fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz vmw_bo->on_validate_list = false; 920fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 921fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 922fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzint vmw_user_dmabuf_lookup(struct ttm_object_file *tfile, 923fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz uint32_t handle, struct vmw_dma_buffer **out) 924fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 925fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_user_dma_buffer *vmw_user_bo; 926fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct ttm_base_object *base; 927fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 928fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz base = ttm_base_object_lookup(tfile, handle); 929fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (unlikely(base == NULL)) { 930fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz printk(KERN_ERR "Invalid buffer object handle 0x%08lx.\n", 931fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz (unsigned long)handle); 932fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return -ESRCH; 933fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz } 934fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 935fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (unlikely(base->object_type != ttm_buffer_type)) { 936fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ttm_base_object_unref(&base); 937fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz printk(KERN_ERR "Invalid buffer object handle 0x%08lx.\n", 938fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz (unsigned long)handle); 939fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return -EINVAL; 940fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz } 941fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 942fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz vmw_user_bo = container_of(base, struct vmw_user_dma_buffer, base); 943fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz (void)ttm_bo_reference(&vmw_user_bo->dma.base); 944fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ttm_base_object_unref(&base); 945fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz *out = &vmw_user_bo->dma; 946fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 947fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return 0; 948fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 949fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 950fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz/* 95165155b3708137fabee865dc4da822763c0c41208Uwe Kleine-König * Stream management 952fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz */ 953fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 954fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzstatic void vmw_stream_destroy(struct vmw_resource *res) 955fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 956fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_private *dev_priv = res->dev_priv; 957fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_stream *stream; 958fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz int ret; 959fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 960fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz DRM_INFO("%s: unref\n", __func__); 961fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz stream = container_of(res, struct vmw_stream, res); 962fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 963fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ret = vmw_overlay_unref(dev_priv, stream->stream_id); 964fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz WARN_ON(ret != 0); 965fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 966fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 967fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzstatic int vmw_stream_init(struct vmw_private *dev_priv, 968fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_stream *stream, 969fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz void (*res_free) (struct vmw_resource *res)) 970fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 971fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_resource *res = &stream->res; 972fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz int ret; 973fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 974fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ret = vmw_resource_init(dev_priv, res, &dev_priv->stream_idr, 975fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz VMW_RES_STREAM, res_free); 976fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 977fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (unlikely(ret != 0)) { 978fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (res_free == NULL) 979fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz kfree(stream); 980fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz else 981fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz res_free(&stream->res); 982fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return ret; 983fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz } 984fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 985fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ret = vmw_overlay_claim(dev_priv, &stream->stream_id); 986fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (ret) { 987fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz vmw_resource_unreference(&res); 988fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return ret; 989fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz } 990fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 991fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz DRM_INFO("%s: claimed\n", __func__); 992fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 993fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz vmw_resource_activate(&stream->res, vmw_stream_destroy); 994fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return 0; 995fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 996fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 997fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz/** 998fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * User-space context management: 999fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz */ 1000fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1001fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzstatic void vmw_user_stream_free(struct vmw_resource *res) 1002fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 1003fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_user_stream *stream = 1004fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz container_of(res, struct vmw_user_stream, stream.res); 1005fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1006fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz kfree(stream); 1007fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 1008fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1009fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz/** 1010fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * This function is called when user space has no more references on the 1011fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * base object. It releases the base-object's reference on the resource object. 1012fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz */ 1013fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1014fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzstatic void vmw_user_stream_base_release(struct ttm_base_object **p_base) 1015fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 1016fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct ttm_base_object *base = *p_base; 1017fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_user_stream *stream = 1018fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz container_of(base, struct vmw_user_stream, base); 1019fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_resource *res = &stream->stream.res; 1020fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1021fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz *p_base = NULL; 1022fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz vmw_resource_unreference(&res); 1023fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 1024fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1025fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzint vmw_stream_unref_ioctl(struct drm_device *dev, void *data, 1026fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct drm_file *file_priv) 1027fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 1028fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_private *dev_priv = vmw_priv(dev); 1029fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_resource *res; 1030fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_user_stream *stream; 1031fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct drm_vmw_stream_arg *arg = (struct drm_vmw_stream_arg *)data; 1032fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile; 1033fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz int ret = 0; 1034fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1035fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz res = vmw_resource_lookup(dev_priv, &dev_priv->stream_idr, arg->stream_id); 1036fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (unlikely(res == NULL)) 1037fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return -EINVAL; 1038fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1039fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (res->res_free != &vmw_user_stream_free) { 1040fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ret = -EINVAL; 1041fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz goto out; 1042fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz } 1043fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1044fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz stream = container_of(res, struct vmw_user_stream, stream.res); 1045fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (stream->base.tfile != tfile) { 1046fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ret = -EINVAL; 1047fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz goto out; 1048fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz } 1049fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1050fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ttm_ref_object_base_unref(tfile, stream->base.hash.key, TTM_REF_USAGE); 1051fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzout: 1052fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz vmw_resource_unreference(&res); 1053fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return ret; 1054fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 1055fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1056fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzint vmw_stream_claim_ioctl(struct drm_device *dev, void *data, 1057fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct drm_file *file_priv) 1058fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 1059fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_private *dev_priv = vmw_priv(dev); 1060fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_user_stream *stream = kmalloc(sizeof(*stream), GFP_KERNEL); 1061fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_resource *res; 1062fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_resource *tmp; 1063fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct drm_vmw_stream_arg *arg = (struct drm_vmw_stream_arg *)data; 1064fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile; 1065fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz int ret; 1066fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1067fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (unlikely(stream == NULL)) 1068fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return -ENOMEM; 1069fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1070fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz res = &stream->stream.res; 1071fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz stream->base.shareable = false; 1072fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz stream->base.tfile = NULL; 1073fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1074fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ret = vmw_stream_init(dev_priv, &stream->stream, vmw_user_stream_free); 1075fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (unlikely(ret != 0)) 1076fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return ret; 1077fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1078fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz tmp = vmw_resource_reference(res); 1079fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ret = ttm_base_object_init(tfile, &stream->base, false, VMW_RES_STREAM, 1080fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz &vmw_user_stream_base_release, NULL); 1081fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1082fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (unlikely(ret != 0)) { 1083fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz vmw_resource_unreference(&tmp); 1084fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz goto out_err; 1085fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz } 1086fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1087fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz arg->stream_id = res->id; 1088fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzout_err: 1089fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz vmw_resource_unreference(&res); 1090fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return ret; 1091fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 1092fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1093fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzint vmw_user_stream_lookup(struct vmw_private *dev_priv, 1094fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct ttm_object_file *tfile, 1095fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz uint32_t *inout_id, struct vmw_resource **out) 1096fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 1097fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_user_stream *stream; 1098fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_resource *res; 1099fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz int ret; 1100fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1101fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz res = vmw_resource_lookup(dev_priv, &dev_priv->stream_idr, *inout_id); 1102fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (unlikely(res == NULL)) 1103fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return -EINVAL; 1104fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1105fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (res->res_free != &vmw_user_stream_free) { 1106fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ret = -EINVAL; 1107fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz goto err_ref; 1108fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz } 1109fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1110fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz stream = container_of(res, struct vmw_user_stream, stream.res); 1111fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (stream->base.tfile != tfile) { 1112fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ret = -EPERM; 1113fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz goto err_ref; 1114fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz } 1115fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1116fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz *inout_id = stream->stream.stream_id; 1117fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz *out = res; 1118fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return 0; 1119fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzerr_ref: 1120fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz vmw_resource_unreference(&res); 1121fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return ret; 1122fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 1123