vmwgfx_resource.c revision 7a73ba7469cbea631050094fd14f73acebb97cf9
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)); 214fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 215fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 216fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzstatic int vmw_context_init(struct vmw_private *dev_priv, 217fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_resource *res, 218fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz void (*res_free) (struct vmw_resource *res)) 219fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 220fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz int ret; 221fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 222fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct { 223fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz SVGA3dCmdHeader header; 224fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz SVGA3dCmdDefineContext body; 225fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz } *cmd; 226fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 227fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ret = vmw_resource_init(dev_priv, res, &dev_priv->context_idr, 228fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz VMW_RES_CONTEXT, res_free); 229fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 230fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (unlikely(ret != 0)) { 231fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (res_free == NULL) 232fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz kfree(res); 233fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz else 234fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz res_free(res); 235fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return ret; 236fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz } 237fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 238fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd)); 239fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (unlikely(cmd == NULL)) { 240fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz DRM_ERROR("Fifo reserve failed.\n"); 241fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz vmw_resource_unreference(&res); 242fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return -ENOMEM; 243fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz } 244fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 245fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz cmd->header.id = cpu_to_le32(SVGA_3D_CMD_CONTEXT_DEFINE); 246fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz cmd->header.size = cpu_to_le32(sizeof(cmd->body)); 247fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz cmd->body.cid = cpu_to_le32(res->id); 248fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 249fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz vmw_fifo_commit(dev_priv, sizeof(*cmd)); 250fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz vmw_resource_activate(res, vmw_hw_context_destroy); 251fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return 0; 252fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 253fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 254fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzstruct vmw_resource *vmw_context_alloc(struct vmw_private *dev_priv) 255fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 256fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_resource *res = kmalloc(sizeof(*res), GFP_KERNEL); 257fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz int ret; 258fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 259fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (unlikely(res == NULL)) 260fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return NULL; 261fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 262fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ret = vmw_context_init(dev_priv, res, NULL); 263fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return (ret == 0) ? res : NULL; 264fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 265fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 266fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz/** 267fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * User-space context management: 268fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz */ 269fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 270fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzstatic void vmw_user_context_free(struct vmw_resource *res) 271fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 272fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_user_context *ctx = 273fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz container_of(res, struct vmw_user_context, res); 274fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 275fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz kfree(ctx); 276fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 277fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 278fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz/** 279fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * This function is called when user space has no more references on the 280fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * base object. It releases the base-object's reference on the resource object. 281fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz */ 282fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 283fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzstatic void vmw_user_context_base_release(struct ttm_base_object **p_base) 284fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 285fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct ttm_base_object *base = *p_base; 286fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_user_context *ctx = 287fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz container_of(base, struct vmw_user_context, base); 288fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_resource *res = &ctx->res; 289fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 290fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz *p_base = NULL; 291fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz vmw_resource_unreference(&res); 292fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 293fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 294fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzint vmw_context_destroy_ioctl(struct drm_device *dev, void *data, 295fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct drm_file *file_priv) 296fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 297fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_private *dev_priv = vmw_priv(dev); 298fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_resource *res; 299fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_user_context *ctx; 300fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct drm_vmw_context_arg *arg = (struct drm_vmw_context_arg *)data; 301fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile; 302fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz int ret = 0; 303fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 304fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz res = vmw_resource_lookup(dev_priv, &dev_priv->context_idr, arg->cid); 305fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (unlikely(res == NULL)) 306fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return -EINVAL; 307fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 308fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (res->res_free != &vmw_user_context_free) { 309fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ret = -EINVAL; 310fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz goto out; 311fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz } 312fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 313fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ctx = container_of(res, struct vmw_user_context, res); 314fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (ctx->base.tfile != tfile && !ctx->base.shareable) { 315fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ret = -EPERM; 316fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz goto out; 317fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz } 318fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 319fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ttm_ref_object_base_unref(tfile, ctx->base.hash.key, TTM_REF_USAGE); 320fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzout: 321fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz vmw_resource_unreference(&res); 322fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return ret; 323fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 324fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 325fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzint vmw_context_define_ioctl(struct drm_device *dev, void *data, 326fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct drm_file *file_priv) 327fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 328fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_private *dev_priv = vmw_priv(dev); 329fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_user_context *ctx = kmalloc(sizeof(*ctx), GFP_KERNEL); 330fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_resource *res; 331fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_resource *tmp; 332fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct drm_vmw_context_arg *arg = (struct drm_vmw_context_arg *)data; 333fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile; 334fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz int ret; 335fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 336fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (unlikely(ctx == NULL)) 337fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return -ENOMEM; 338fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 339fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz res = &ctx->res; 340fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ctx->base.shareable = false; 341fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ctx->base.tfile = NULL; 342fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 343fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ret = vmw_context_init(dev_priv, res, vmw_user_context_free); 344fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (unlikely(ret != 0)) 345fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return ret; 346fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 347fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz tmp = vmw_resource_reference(&ctx->res); 348fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ret = ttm_base_object_init(tfile, &ctx->base, false, VMW_RES_CONTEXT, 349fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz &vmw_user_context_base_release, NULL); 350fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 351fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (unlikely(ret != 0)) { 352fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz vmw_resource_unreference(&tmp); 353fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz goto out_err; 354fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz } 355fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 356fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz arg->cid = res->id; 357fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzout_err: 358fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz vmw_resource_unreference(&res); 359fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return ret; 360fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 361fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 362fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 363fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzint vmw_context_check(struct vmw_private *dev_priv, 364fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct ttm_object_file *tfile, 365fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz int id) 366fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 367fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_resource *res; 368fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz int ret = 0; 369fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 370fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz read_lock(&dev_priv->resource_lock); 371fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz res = idr_find(&dev_priv->context_idr, id); 372fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (res && res->avail) { 373fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_user_context *ctx = 374fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz container_of(res, struct vmw_user_context, res); 375fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (ctx->base.tfile != tfile && !ctx->base.shareable) 376fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ret = -EPERM; 377fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz } else 378fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ret = -EINVAL; 379fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz read_unlock(&dev_priv->resource_lock); 380fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 381fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return ret; 382fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 383fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 384fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 385fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz/** 386fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * Surface management. 387fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz */ 388fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 389fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzstatic void vmw_hw_surface_destroy(struct vmw_resource *res) 390fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 391fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 392fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_private *dev_priv = res->dev_priv; 393fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct { 394fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz SVGA3dCmdHeader header; 395fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz SVGA3dCmdDestroySurface body; 396fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz } *cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd)); 397fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 398fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (unlikely(cmd == NULL)) { 399fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz DRM_ERROR("Failed reserving FIFO space for surface " 400fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz "destruction.\n"); 401fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return; 402fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz } 403fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 404fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz cmd->header.id = cpu_to_le32(SVGA_3D_CMD_SURFACE_DESTROY); 405fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz cmd->header.size = cpu_to_le32(sizeof(cmd->body)); 406fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz cmd->body.sid = cpu_to_le32(res->id); 407fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 408fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz vmw_fifo_commit(dev_priv, sizeof(*cmd)); 409fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 410fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 411fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzvoid vmw_surface_res_free(struct vmw_resource *res) 412fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 413fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_surface *srf = container_of(res, struct vmw_surface, res); 414fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 415fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz kfree(srf->sizes); 416fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz kfree(srf->snooper.image); 417fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz kfree(srf); 418fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 419fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 420fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzint vmw_surface_init(struct vmw_private *dev_priv, 421fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_surface *srf, 422fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz void (*res_free) (struct vmw_resource *res)) 423fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 424fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz int ret; 425fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct { 426fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz SVGA3dCmdHeader header; 427fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz SVGA3dCmdDefineSurface body; 428fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz } *cmd; 429fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz SVGA3dSize *cmd_size; 430fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_resource *res = &srf->res; 431fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct drm_vmw_size *src_size; 432fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz size_t submit_size; 433fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz uint32_t cmd_len; 434fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz int i; 435fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 436fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz BUG_ON(res_free == NULL); 437fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ret = vmw_resource_init(dev_priv, res, &dev_priv->surface_idr, 438fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz VMW_RES_SURFACE, res_free); 439fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 440fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (unlikely(ret != 0)) { 441fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz res_free(res); 442fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return ret; 443fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz } 444fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 445fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz submit_size = sizeof(*cmd) + srf->num_sizes * sizeof(SVGA3dSize); 446fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz cmd_len = sizeof(cmd->body) + srf->num_sizes * sizeof(SVGA3dSize); 447fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 448fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz cmd = vmw_fifo_reserve(dev_priv, submit_size); 449fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (unlikely(cmd == NULL)) { 450fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz DRM_ERROR("Fifo reserve failed for create surface.\n"); 451fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz vmw_resource_unreference(&res); 452fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return -ENOMEM; 453fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz } 454fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 455fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz cmd->header.id = cpu_to_le32(SVGA_3D_CMD_SURFACE_DEFINE); 456fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz cmd->header.size = cpu_to_le32(cmd_len); 457fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz cmd->body.sid = cpu_to_le32(res->id); 458fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz cmd->body.surfaceFlags = cpu_to_le32(srf->flags); 459fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz cmd->body.format = cpu_to_le32(srf->format); 460fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz for (i = 0; i < DRM_VMW_MAX_SURFACE_FACES; ++i) { 461fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz cmd->body.face[i].numMipLevels = 462fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz cpu_to_le32(srf->mip_levels[i]); 463fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz } 464fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 465fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz cmd += 1; 466fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz cmd_size = (SVGA3dSize *) cmd; 467fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz src_size = srf->sizes; 468fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 469fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz for (i = 0; i < srf->num_sizes; ++i, cmd_size++, src_size++) { 470fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz cmd_size->width = cpu_to_le32(src_size->width); 471fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz cmd_size->height = cpu_to_le32(src_size->height); 472fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz cmd_size->depth = cpu_to_le32(src_size->depth); 473fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz } 474fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 475fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz vmw_fifo_commit(dev_priv, submit_size); 476fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz vmw_resource_activate(res, vmw_hw_surface_destroy); 477fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return 0; 478fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 479fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 480fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzstatic void vmw_user_surface_free(struct vmw_resource *res) 481fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 482fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_surface *srf = container_of(res, struct vmw_surface, res); 483fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_user_surface *user_srf = 484fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz container_of(srf, struct vmw_user_surface, srf); 485fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 486fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz kfree(srf->sizes); 487fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz kfree(srf->snooper.image); 488fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz kfree(user_srf); 489fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 490fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 4917a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstromint vmw_user_surface_lookup_handle(struct vmw_private *dev_priv, 4927a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom struct ttm_object_file *tfile, 4937a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom uint32_t handle, struct vmw_surface **out) 494fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 495fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_resource *res; 496fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_surface *srf; 497fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_user_surface *user_srf; 4987a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom struct ttm_base_object *base; 4997a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom int ret = -EINVAL; 500fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 5017a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom base = ttm_base_object_lookup(tfile, handle); 5027a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom if (unlikely(base == NULL)) 503fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return -EINVAL; 504fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 5057a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom if (unlikely(base->object_type != VMW_RES_SURFACE)) 5067a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom goto out_bad_resource; 5077a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom 5087a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom user_srf = container_of(base, struct vmw_user_surface, base); 5097a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom srf = &user_srf->srf; 5107a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom res = &srf->res; 5117a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom 5127a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom read_lock(&dev_priv->resource_lock); 5137a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom 5147a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom if (!res->avail || res->res_free != &vmw_user_surface_free) { 5157a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom read_unlock(&dev_priv->resource_lock); 5167a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom goto out_bad_resource; 5177a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom } 518fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 5197a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom kref_get(&res->kref); 5207a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom read_unlock(&dev_priv->resource_lock); 521fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 522fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz *out = srf; 5237a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom ret = 0; 5247a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom 5257a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstromout_bad_resource: 5267a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom ttm_base_object_unref(&base); 5277a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom 5287a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom return ret; 529fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 530fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 531fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzstatic void vmw_user_surface_base_release(struct ttm_base_object **p_base) 532fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 533fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct ttm_base_object *base = *p_base; 534fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_user_surface *user_srf = 535fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz container_of(base, struct vmw_user_surface, base); 536fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_resource *res = &user_srf->srf.res; 537fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 538fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz *p_base = NULL; 539fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz vmw_resource_unreference(&res); 540fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 541fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 542fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzint vmw_surface_destroy_ioctl(struct drm_device *dev, void *data, 543fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct drm_file *file_priv) 544fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 545fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct drm_vmw_surface_arg *arg = (struct drm_vmw_surface_arg *)data; 546fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile; 547fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 5487a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom return ttm_ref_object_base_unref(tfile, arg->sid, TTM_REF_USAGE); 549fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 550fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 551fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzint vmw_surface_define_ioctl(struct drm_device *dev, void *data, 552fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct drm_file *file_priv) 553fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 554fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_private *dev_priv = vmw_priv(dev); 555fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_user_surface *user_srf = 556fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz kmalloc(sizeof(*user_srf), GFP_KERNEL); 557fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_surface *srf; 558fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_resource *res; 559fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_resource *tmp; 560fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz union drm_vmw_surface_create_arg *arg = 561fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz (union drm_vmw_surface_create_arg *)data; 562fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct drm_vmw_surface_create_req *req = &arg->req; 563fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct drm_vmw_surface_arg *rep = &arg->rep; 564fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile; 565fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct drm_vmw_size __user *user_sizes; 566fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz int ret; 567fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz int i; 568fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 569fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (unlikely(user_srf == NULL)) 570fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return -ENOMEM; 571fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 572fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz srf = &user_srf->srf; 573fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz res = &srf->res; 574fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 575fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz srf->flags = req->flags; 576fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz srf->format = req->format; 577fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz memcpy(srf->mip_levels, req->mip_levels, sizeof(srf->mip_levels)); 578fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz srf->num_sizes = 0; 579fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz for (i = 0; i < DRM_VMW_MAX_SURFACE_FACES; ++i) 580fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz srf->num_sizes += srf->mip_levels[i]; 581fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 582fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (srf->num_sizes > DRM_VMW_MAX_SURFACE_FACES * 583fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz DRM_VMW_MAX_MIP_LEVELS) { 584fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ret = -EINVAL; 585fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz goto out_err0; 586fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz } 587fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 588fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz srf->sizes = kmalloc(srf->num_sizes * sizeof(*srf->sizes), GFP_KERNEL); 589fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (unlikely(srf->sizes == NULL)) { 590fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ret = -ENOMEM; 591fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz goto out_err0; 592fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz } 593fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 594fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz user_sizes = (struct drm_vmw_size __user *)(unsigned long) 595fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz req->size_addr; 596fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 597fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ret = copy_from_user(srf->sizes, user_sizes, 598fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz srf->num_sizes * sizeof(*srf->sizes)); 599fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (unlikely(ret != 0)) 600fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz goto out_err1; 601fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 602fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz user_srf->base.shareable = false; 603fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz user_srf->base.tfile = NULL; 604fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 605fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz /** 606fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * From this point, the generic resource management functions 607fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * destroy the object on failure. 608fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz */ 609fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 610fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ret = vmw_surface_init(dev_priv, srf, vmw_user_surface_free); 611fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (unlikely(ret != 0)) 612fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return ret; 613fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 614fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz tmp = vmw_resource_reference(&srf->res); 615fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ret = ttm_base_object_init(tfile, &user_srf->base, 616fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz req->shareable, VMW_RES_SURFACE, 617fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz &vmw_user_surface_base_release, NULL); 618fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 619fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (unlikely(ret != 0)) { 620fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz vmw_resource_unreference(&tmp); 621fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz vmw_resource_unreference(&res); 622fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return ret; 623fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz } 624fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 625fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (srf->flags & (1 << 9) && 626fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz srf->num_sizes == 1 && 627fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz srf->sizes[0].width == 64 && 628fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz srf->sizes[0].height == 64 && 629fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz srf->format == SVGA3D_A8R8G8B8) { 630fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 631fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz srf->snooper.image = kmalloc(64 * 64 * 4, GFP_KERNEL); 632fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz /* clear the image */ 633fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (srf->snooper.image) 634fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz memset(srf->snooper.image, 0x00, 64 * 64 * 4); 635fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz else 636fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz DRM_ERROR("Failed to allocate cursor_image\n"); 637fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 638fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz } else { 639fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz srf->snooper.image = NULL; 640fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz } 641fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz srf->snooper.crtc = NULL; 642fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 6437a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom rep->sid = user_srf->base.hash.key; 6447a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom if (rep->sid == SVGA3D_INVALID_ID) 6457a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom DRM_ERROR("Created bad Surface ID.\n"); 6467a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom 647fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz vmw_resource_unreference(&res); 648fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return 0; 649fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzout_err1: 650fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz kfree(srf->sizes); 651fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzout_err0: 652fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz kfree(user_srf); 653fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return ret; 654fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 655fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 656fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzint vmw_surface_reference_ioctl(struct drm_device *dev, void *data, 657fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct drm_file *file_priv) 658fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 659fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz union drm_vmw_surface_reference_arg *arg = 660fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz (union drm_vmw_surface_reference_arg *)data; 661fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct drm_vmw_surface_arg *req = &arg->req; 662fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct drm_vmw_surface_create_req *rep = &arg->rep; 663fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile; 664fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_surface *srf; 665fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_user_surface *user_srf; 666fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct drm_vmw_size __user *user_sizes; 6677a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom struct ttm_base_object *base; 6687a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom int ret = -EINVAL; 669fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 6707a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom base = ttm_base_object_lookup(tfile, req->sid); 6717a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom if (unlikely(base == NULL)) { 6727a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom DRM_ERROR("Could not find surface to reference.\n"); 673fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return -EINVAL; 674fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz } 675fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 6767a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom if (unlikely(base->object_type != VMW_RES_SURFACE)) 6777a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom goto out_bad_resource; 6787a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom 6797a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom user_srf = container_of(base, struct vmw_user_surface, base); 6807a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom srf = &user_srf->srf; 681fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 682fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ret = ttm_ref_object_add(tfile, &user_srf->base, TTM_REF_USAGE, NULL); 683fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (unlikely(ret != 0)) { 684fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz DRM_ERROR("Could not add a reference to a surface.\n"); 6857a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom goto out_no_reference; 686fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz } 687fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 688fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz rep->flags = srf->flags; 689fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz rep->format = srf->format; 690fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz memcpy(rep->mip_levels, srf->mip_levels, sizeof(srf->mip_levels)); 691fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz user_sizes = (struct drm_vmw_size __user *)(unsigned long) 692fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz rep->size_addr; 693fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 694fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (user_sizes) 695fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ret = copy_to_user(user_sizes, srf->sizes, 696fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz srf->num_sizes * sizeof(*srf->sizes)); 6977a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom if (unlikely(ret != 0)) 698fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz DRM_ERROR("copy_to_user failed %p %u\n", 699fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz user_sizes, srf->num_sizes); 7007a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstromout_bad_resource: 7017a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstromout_no_reference: 7027a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom ttm_base_object_unref(&base); 7037a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom 704fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return ret; 705fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 706fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 707fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzint vmw_surface_check(struct vmw_private *dev_priv, 708fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct ttm_object_file *tfile, 7097a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom uint32_t handle, int *id) 710fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 7117a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom struct ttm_base_object *base; 7127a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom struct vmw_user_surface *user_srf; 713fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 7147a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom int ret = -EPERM; 715fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 7167a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom base = ttm_base_object_lookup(tfile, handle); 7177a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom if (unlikely(base == NULL)) 7187a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom return -EINVAL; 7197a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom 7207a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom if (unlikely(base->object_type != VMW_RES_SURFACE)) 7217a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom goto out_bad_surface; 7227a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom 7237a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom user_srf = container_of(base, struct vmw_user_surface, base); 7247a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom *id = user_srf->srf.res.id; 7257a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom ret = 0; 7267a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom 7277a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstromout_bad_surface: 7287a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom /** 7297a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom * FIXME: May deadlock here when called from the 7307a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom * command parsing code. 7317a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom */ 732fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 7337a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom ttm_base_object_unref(&base); 734fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return ret; 735fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 736fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 737fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz/** 738fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * Buffer management. 739fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz */ 740fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 741fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzstatic size_t vmw_dmabuf_acc_size(struct ttm_bo_global *glob, 742fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz unsigned long num_pages) 743fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 744fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz static size_t bo_user_size = ~0; 745fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 746fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz size_t page_array_size = 747fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz (num_pages * sizeof(void *) + PAGE_SIZE - 1) & PAGE_MASK; 748fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 749fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (unlikely(bo_user_size == ~0)) { 750fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz bo_user_size = glob->ttm_bo_extra_size + 751fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ttm_round_pot(sizeof(struct vmw_dma_buffer)); 752fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz } 753fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 754fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return bo_user_size + page_array_size; 755fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 756fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 757fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzvoid vmw_dmabuf_bo_free(struct ttm_buffer_object *bo) 758fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 759fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_dma_buffer *vmw_bo = vmw_dma_buffer(bo); 760fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct ttm_bo_global *glob = bo->glob; 761fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_private *dev_priv = 762fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz container_of(bo->bdev, struct vmw_private, bdev); 763fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 764fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ttm_mem_global_free(glob->mem_glob, bo->acc_size); 765fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (vmw_bo->gmr_bound) { 766fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz vmw_gmr_unbind(dev_priv, vmw_bo->gmr_id); 767fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz spin_lock(&glob->lru_lock); 768fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ida_remove(&dev_priv->gmr_ida, vmw_bo->gmr_id); 769fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz spin_unlock(&glob->lru_lock); 770fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz } 771fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz kfree(vmw_bo); 772fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 773fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 774fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzint vmw_dmabuf_init(struct vmw_private *dev_priv, 775fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_dma_buffer *vmw_bo, 776fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz size_t size, struct ttm_placement *placement, 777fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz bool interruptible, 778fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz void (*bo_free) (struct ttm_buffer_object *bo)) 779fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 780fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct ttm_bo_device *bdev = &dev_priv->bdev; 781fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct ttm_mem_global *mem_glob = bdev->glob->mem_glob; 782fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz size_t acc_size; 783fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz int ret; 784fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 785fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz BUG_ON(!bo_free); 786fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 787fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz acc_size = 788fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz vmw_dmabuf_acc_size(bdev->glob, 789fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz (size + PAGE_SIZE - 1) >> PAGE_SHIFT); 790fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 791fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ret = ttm_mem_global_alloc(mem_glob, acc_size, false, false); 792fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (unlikely(ret != 0)) { 793fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz /* we must free the bo here as 794fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * ttm_buffer_object_init does so as well */ 795fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz bo_free(&vmw_bo->base); 796fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return ret; 797fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz } 798fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 799fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz memset(vmw_bo, 0, sizeof(*vmw_bo)); 800fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 801fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz INIT_LIST_HEAD(&vmw_bo->gmr_lru); 802fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz INIT_LIST_HEAD(&vmw_bo->validate_list); 803fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz vmw_bo->gmr_id = 0; 804fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz vmw_bo->gmr_bound = false; 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 vmw_dma_buffer *vmw_bo = &vmw_user_bo->dma; 817fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct ttm_bo_global *glob = bo->glob; 818fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_private *dev_priv = 819fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz container_of(bo->bdev, struct vmw_private, bdev); 820fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 821fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ttm_mem_global_free(glob->mem_glob, bo->acc_size); 822fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (vmw_bo->gmr_bound) { 823fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz vmw_gmr_unbind(dev_priv, vmw_bo->gmr_id); 824fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz spin_lock(&glob->lru_lock); 825fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ida_remove(&dev_priv->gmr_ida, vmw_bo->gmr_id); 826fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz spin_unlock(&glob->lru_lock); 827fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz } 828fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz kfree(vmw_user_bo); 829fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 830fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 831fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzstatic void vmw_user_dmabuf_release(struct ttm_base_object **p_base) 832fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 833fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_user_dma_buffer *vmw_user_bo; 834fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct ttm_base_object *base = *p_base; 835fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct ttm_buffer_object *bo; 836fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 837fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz *p_base = NULL; 838fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 839fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (unlikely(base == NULL)) 840fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return; 841fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 842fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz vmw_user_bo = container_of(base, struct vmw_user_dma_buffer, base); 843fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz bo = &vmw_user_bo->dma.base; 844fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ttm_bo_unref(&bo); 845fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 846fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 847fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzint vmw_dmabuf_alloc_ioctl(struct drm_device *dev, void *data, 848fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct drm_file *file_priv) 849fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 850fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_private *dev_priv = vmw_priv(dev); 851fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz union drm_vmw_alloc_dmabuf_arg *arg = 852fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz (union drm_vmw_alloc_dmabuf_arg *)data; 853fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct drm_vmw_alloc_dmabuf_req *req = &arg->req; 854fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct drm_vmw_dmabuf_rep *rep = &arg->rep; 855fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_user_dma_buffer *vmw_user_bo; 856fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct ttm_buffer_object *tmp; 857fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_master *vmaster = vmw_master(file_priv->master); 858fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz int ret; 859fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 860fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz vmw_user_bo = kzalloc(sizeof(*vmw_user_bo), GFP_KERNEL); 861fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (unlikely(vmw_user_bo == NULL)) 862fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return -ENOMEM; 863fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 864fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ret = ttm_read_lock(&vmaster->lock, true); 865fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (unlikely(ret != 0)) { 866fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz kfree(vmw_user_bo); 867fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return ret; 868fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz } 869fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 870fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ret = vmw_dmabuf_init(dev_priv, &vmw_user_bo->dma, req->size, 871fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz &vmw_vram_placement, true, 872fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz &vmw_user_dmabuf_destroy); 873fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (unlikely(ret != 0)) 874fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return ret; 875fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 876fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz tmp = ttm_bo_reference(&vmw_user_bo->dma.base); 877fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ret = ttm_base_object_init(vmw_fpriv(file_priv)->tfile, 878fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz &vmw_user_bo->base, 879fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz false, 880fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ttm_buffer_type, 881fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz &vmw_user_dmabuf_release, NULL); 882fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (unlikely(ret != 0)) { 883fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ttm_bo_unref(&tmp); 884fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz } else { 885fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz rep->handle = vmw_user_bo->base.hash.key; 886fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz rep->map_handle = vmw_user_bo->dma.base.addr_space_offset; 887fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz rep->cur_gmr_id = vmw_user_bo->base.hash.key; 888fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz rep->cur_gmr_offset = 0; 889fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz } 890fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ttm_bo_unref(&tmp); 891fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 892fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ttm_read_unlock(&vmaster->lock); 893fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 894fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return 0; 895fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 896fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 897fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzint vmw_dmabuf_unref_ioctl(struct drm_device *dev, void *data, 898fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct drm_file *file_priv) 899fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 900fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct drm_vmw_unref_dmabuf_arg *arg = 901fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz (struct drm_vmw_unref_dmabuf_arg *)data; 902fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 903fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return ttm_ref_object_base_unref(vmw_fpriv(file_priv)->tfile, 904fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz arg->handle, 905fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz TTM_REF_USAGE); 906fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 907fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 908fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzuint32_t vmw_dmabuf_validate_node(struct ttm_buffer_object *bo, 909fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz uint32_t cur_validate_node) 910fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 911fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_dma_buffer *vmw_bo = vmw_dma_buffer(bo); 912fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 913fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (likely(vmw_bo->on_validate_list)) 914fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return vmw_bo->cur_validate_node; 915fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 916fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz vmw_bo->cur_validate_node = cur_validate_node; 917fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz vmw_bo->on_validate_list = true; 918fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 919fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return cur_validate_node; 920fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 921fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 922fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzvoid vmw_dmabuf_validate_clear(struct ttm_buffer_object *bo) 923fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 924fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_dma_buffer *vmw_bo = vmw_dma_buffer(bo); 925fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 926fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz vmw_bo->on_validate_list = false; 927fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 928fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 929fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzuint32_t vmw_dmabuf_gmr(struct ttm_buffer_object *bo) 930fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 931fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_dma_buffer *vmw_bo; 932fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 933fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (bo->mem.mem_type == TTM_PL_VRAM) 934fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return SVGA_GMR_FRAMEBUFFER; 935fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 936fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz vmw_bo = vmw_dma_buffer(bo); 937fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 938fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return (vmw_bo->gmr_bound) ? vmw_bo->gmr_id : SVGA_GMR_NULL; 939fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 940fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 941fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzvoid vmw_dmabuf_set_gmr(struct ttm_buffer_object *bo, uint32_t id) 942fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 943fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_dma_buffer *vmw_bo = vmw_dma_buffer(bo); 944fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz vmw_bo->gmr_bound = true; 945fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz vmw_bo->gmr_id = id; 946fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 947fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 948fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzint vmw_user_dmabuf_lookup(struct ttm_object_file *tfile, 949fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz uint32_t handle, struct vmw_dma_buffer **out) 950fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 951fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_user_dma_buffer *vmw_user_bo; 952fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct ttm_base_object *base; 953fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 954fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz base = ttm_base_object_lookup(tfile, handle); 955fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (unlikely(base == NULL)) { 956fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz printk(KERN_ERR "Invalid buffer object handle 0x%08lx.\n", 957fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz (unsigned long)handle); 958fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return -ESRCH; 959fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz } 960fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 961fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (unlikely(base->object_type != ttm_buffer_type)) { 962fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ttm_base_object_unref(&base); 963fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz printk(KERN_ERR "Invalid buffer object handle 0x%08lx.\n", 964fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz (unsigned long)handle); 965fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return -EINVAL; 966fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz } 967fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 968fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz vmw_user_bo = container_of(base, struct vmw_user_dma_buffer, base); 969fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz (void)ttm_bo_reference(&vmw_user_bo->dma.base); 970fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ttm_base_object_unref(&base); 971fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz *out = &vmw_user_bo->dma; 972fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 973fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return 0; 974fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 975fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 976fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz/** 977fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * TODO: Implement a gmr id eviction mechanism. Currently we just fail 978fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * when we're out of ids, causing GMR space to be allocated 979fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * out of VRAM. 980fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz */ 981fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 982fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzint vmw_gmr_id_alloc(struct vmw_private *dev_priv, uint32_t *p_id) 983fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 984fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct ttm_bo_global *glob = dev_priv->bdev.glob; 985fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz int id; 986fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz int ret; 987fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 988fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz do { 989fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (unlikely(ida_pre_get(&dev_priv->gmr_ida, GFP_KERNEL) == 0)) 990fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return -ENOMEM; 991fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 992fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz spin_lock(&glob->lru_lock); 993fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ret = ida_get_new(&dev_priv->gmr_ida, &id); 994fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz spin_unlock(&glob->lru_lock); 995fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz } while (ret == -EAGAIN); 996fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 997fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (unlikely(ret != 0)) 998fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return ret; 999fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1000fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (unlikely(id >= dev_priv->max_gmr_ids)) { 1001fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz spin_lock(&glob->lru_lock); 1002fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ida_remove(&dev_priv->gmr_ida, id); 1003fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz spin_unlock(&glob->lru_lock); 1004fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return -EBUSY; 1005fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz } 1006fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1007fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz *p_id = (uint32_t) id; 1008fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return 0; 1009fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 1010fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1011fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz/* 1012fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * Stream managment 1013fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz */ 1014fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1015fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzstatic void vmw_stream_destroy(struct vmw_resource *res) 1016fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 1017fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_private *dev_priv = res->dev_priv; 1018fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_stream *stream; 1019fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz int ret; 1020fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1021fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz DRM_INFO("%s: unref\n", __func__); 1022fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz stream = container_of(res, struct vmw_stream, res); 1023fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1024fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ret = vmw_overlay_unref(dev_priv, stream->stream_id); 1025fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz WARN_ON(ret != 0); 1026fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 1027fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1028fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzstatic int vmw_stream_init(struct vmw_private *dev_priv, 1029fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_stream *stream, 1030fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz void (*res_free) (struct vmw_resource *res)) 1031fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 1032fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_resource *res = &stream->res; 1033fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz int ret; 1034fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1035fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ret = vmw_resource_init(dev_priv, res, &dev_priv->stream_idr, 1036fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz VMW_RES_STREAM, res_free); 1037fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1038fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (unlikely(ret != 0)) { 1039fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (res_free == NULL) 1040fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz kfree(stream); 1041fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz else 1042fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz res_free(&stream->res); 1043fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return ret; 1044fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz } 1045fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1046fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ret = vmw_overlay_claim(dev_priv, &stream->stream_id); 1047fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (ret) { 1048fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz vmw_resource_unreference(&res); 1049fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return ret; 1050fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz } 1051fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1052fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz DRM_INFO("%s: claimed\n", __func__); 1053fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1054fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz vmw_resource_activate(&stream->res, vmw_stream_destroy); 1055fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return 0; 1056fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 1057fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1058fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz/** 1059fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * User-space context management: 1060fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz */ 1061fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1062fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzstatic void vmw_user_stream_free(struct vmw_resource *res) 1063fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 1064fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_user_stream *stream = 1065fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz container_of(res, struct vmw_user_stream, stream.res); 1066fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1067fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz kfree(stream); 1068fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 1069fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1070fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz/** 1071fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * This function is called when user space has no more references on the 1072fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * base object. It releases the base-object's reference on the resource object. 1073fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz */ 1074fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1075fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzstatic void vmw_user_stream_base_release(struct ttm_base_object **p_base) 1076fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 1077fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct ttm_base_object *base = *p_base; 1078fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_user_stream *stream = 1079fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz container_of(base, struct vmw_user_stream, base); 1080fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_resource *res = &stream->stream.res; 1081fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1082fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz *p_base = NULL; 1083fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz vmw_resource_unreference(&res); 1084fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 1085fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1086fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzint vmw_stream_unref_ioctl(struct drm_device *dev, void *data, 1087fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct drm_file *file_priv) 1088fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 1089fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_private *dev_priv = vmw_priv(dev); 1090fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_resource *res; 1091fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_user_stream *stream; 1092fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct drm_vmw_stream_arg *arg = (struct drm_vmw_stream_arg *)data; 1093fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile; 1094fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz int ret = 0; 1095fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1096fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz res = vmw_resource_lookup(dev_priv, &dev_priv->stream_idr, arg->stream_id); 1097fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (unlikely(res == NULL)) 1098fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return -EINVAL; 1099fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1100fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (res->res_free != &vmw_user_stream_free) { 1101fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ret = -EINVAL; 1102fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz goto out; 1103fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz } 1104fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1105fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz stream = container_of(res, struct vmw_user_stream, stream.res); 1106fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (stream->base.tfile != tfile) { 1107fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ret = -EINVAL; 1108fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz goto out; 1109fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz } 1110fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1111fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ttm_ref_object_base_unref(tfile, stream->base.hash.key, TTM_REF_USAGE); 1112fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzout: 1113fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz vmw_resource_unreference(&res); 1114fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return ret; 1115fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 1116fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1117fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzint vmw_stream_claim_ioctl(struct drm_device *dev, void *data, 1118fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct drm_file *file_priv) 1119fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 1120fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_private *dev_priv = vmw_priv(dev); 1121fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_user_stream *stream = kmalloc(sizeof(*stream), GFP_KERNEL); 1122fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_resource *res; 1123fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_resource *tmp; 1124fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct drm_vmw_stream_arg *arg = (struct drm_vmw_stream_arg *)data; 1125fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile; 1126fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz int ret; 1127fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1128fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (unlikely(stream == NULL)) 1129fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return -ENOMEM; 1130fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1131fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz res = &stream->stream.res; 1132fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz stream->base.shareable = false; 1133fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz stream->base.tfile = NULL; 1134fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1135fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ret = vmw_stream_init(dev_priv, &stream->stream, vmw_user_stream_free); 1136fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (unlikely(ret != 0)) 1137fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return ret; 1138fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1139fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz tmp = vmw_resource_reference(res); 1140fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ret = ttm_base_object_init(tfile, &stream->base, false, VMW_RES_STREAM, 1141fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz &vmw_user_stream_base_release, NULL); 1142fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1143fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (unlikely(ret != 0)) { 1144fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz vmw_resource_unreference(&tmp); 1145fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz goto out_err; 1146fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz } 1147fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1148fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz arg->stream_id = res->id; 1149fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzout_err: 1150fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz vmw_resource_unreference(&res); 1151fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return ret; 1152fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 1153fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1154fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzint vmw_user_stream_lookup(struct vmw_private *dev_priv, 1155fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct ttm_object_file *tfile, 1156fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz uint32_t *inout_id, struct vmw_resource **out) 1157fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 1158fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_user_stream *stream; 1159fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_resource *res; 1160fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz int ret; 1161fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1162fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz res = vmw_resource_lookup(dev_priv, &dev_priv->stream_idr, *inout_id); 1163fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (unlikely(res == NULL)) 1164fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return -EINVAL; 1165fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1166fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (res->res_free != &vmw_user_stream_free) { 1167fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ret = -EINVAL; 1168fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz goto err_ref; 1169fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz } 1170fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1171fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz stream = container_of(res, struct vmw_user_stream, stream.res); 1172fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (stream->base.tfile != tfile) { 1173fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ret = -EPERM; 1174fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz goto err_ref; 1175fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz } 1176fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1177fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz *inout_id = stream->stream.stream_id; 1178fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz *out = res; 1179fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return 0; 1180fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzerr_ref: 1181fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz vmw_resource_unreference(&res); 1182fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return ret; 1183fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 1184