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