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 Bornecrantzstruct vmw_user_context { 35fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct ttm_base_object base; 36fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_resource res; 37fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz}; 38fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 39fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzstruct vmw_user_surface { 40fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct ttm_base_object base; 41fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_surface srf; 42414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom uint32_t size; 43fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz}; 44fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 45fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzstruct vmw_user_dma_buffer { 46fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct ttm_base_object base; 47fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_dma_buffer dma; 48fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz}; 49fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 50fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzstruct vmw_bo_user_rep { 51fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz uint32_t handle; 52fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz uint64_t map_handle; 53fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz}; 54fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 55fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzstruct vmw_stream { 56fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_resource res; 57fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz uint32_t stream_id; 58fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz}; 59fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 60fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzstruct vmw_user_stream { 61fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct ttm_base_object base; 62fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_stream stream; 63fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz}; 64fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 655bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstromstruct vmw_surface_offset { 665bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom uint32_t face; 675bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom uint32_t mip; 685bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom uint32_t bo_offset; 695bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom}; 705bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom 71414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom 72414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstromstatic uint64_t vmw_user_context_size; 73414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstromstatic uint64_t vmw_user_surface_size; 74414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstromstatic uint64_t vmw_user_stream_size; 75414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom 76fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzstatic inline struct vmw_dma_buffer * 77fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzvmw_dma_buffer(struct ttm_buffer_object *bo) 78fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 79fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return container_of(bo, struct vmw_dma_buffer, base); 80fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 81fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 82fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzstatic inline struct vmw_user_dma_buffer * 83fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzvmw_user_dma_buffer(struct ttm_buffer_object *bo) 84fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 85fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_dma_buffer *vmw_bo = vmw_dma_buffer(bo); 86fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return container_of(vmw_bo, struct vmw_user_dma_buffer, dma); 87fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 88fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 89fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzstruct vmw_resource *vmw_resource_reference(struct vmw_resource *res) 90fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 91fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz kref_get(&res->kref); 92fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return res; 93fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 94fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 955bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom 965bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom/** 975bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom * vmw_resource_release_id - release a resource id to the id manager. 985bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom * 995bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom * @res: Pointer to the resource. 1005bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom * 1015bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom * Release the resource id to the resource id manager and set it to -1 1025bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom */ 1035bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstromstatic void vmw_resource_release_id(struct vmw_resource *res) 1045bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom{ 1055bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom struct vmw_private *dev_priv = res->dev_priv; 1065bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom 1075bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom write_lock(&dev_priv->resource_lock); 1085bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom if (res->id != -1) 1095bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom idr_remove(res->idr, res->id); 1105bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom res->id = -1; 1115bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom write_unlock(&dev_priv->resource_lock); 1125bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom} 1135bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom 114fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzstatic void vmw_resource_release(struct kref *kref) 115fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 116fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_resource *res = 117fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz container_of(kref, struct vmw_resource, kref); 118fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_private *dev_priv = res->dev_priv; 1195bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom int id = res->id; 1205bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom struct idr *idr = res->idr; 121fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1225bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom res->avail = false; 1235bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom if (res->remove_from_lists != NULL) 1245bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom res->remove_from_lists(res); 125fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz write_unlock(&dev_priv->resource_lock); 126fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 127fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (likely(res->hw_destroy != NULL)) 128fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz res->hw_destroy(res); 129fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 130fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (res->res_free != NULL) 131fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz res->res_free(res); 132fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz else 133fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz kfree(res); 134fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 135fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz write_lock(&dev_priv->resource_lock); 1365bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom 1375bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom if (id != -1) 1385bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom idr_remove(idr, id); 139fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 140fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 141fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzvoid vmw_resource_unreference(struct vmw_resource **p_res) 142fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 143fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_resource *res = *p_res; 144fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_private *dev_priv = res->dev_priv; 145fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 146fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz *p_res = NULL; 147fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz write_lock(&dev_priv->resource_lock); 148fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz kref_put(&res->kref, vmw_resource_release); 149fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz write_unlock(&dev_priv->resource_lock); 150fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 151fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1525bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom 1535bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom/** 1545bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom * vmw_resource_alloc_id - release a resource id to the id manager. 1555bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom * 1565bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom * @dev_priv: Pointer to the device private structure. 1575bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom * @res: Pointer to the resource. 1585bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom * 1595bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom * Allocate the lowest free resource from the resource manager, and set 1605bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom * @res->id to that id. Returns 0 on success and -ENOMEM on failure. 1615bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom */ 1625bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstromstatic int vmw_resource_alloc_id(struct vmw_private *dev_priv, 1635bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom struct vmw_resource *res) 1645bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom{ 1655bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom int ret; 1665bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom 1675bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom BUG_ON(res->id != -1); 1685bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom 1695bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom do { 1705bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom if (unlikely(idr_pre_get(res->idr, GFP_KERNEL) == 0)) 1715bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom return -ENOMEM; 1725bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom 1735bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom write_lock(&dev_priv->resource_lock); 1745bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom ret = idr_get_new_above(res->idr, res, 1, &res->id); 1755bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom write_unlock(&dev_priv->resource_lock); 1765bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom 1775bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom } while (ret == -EAGAIN); 1785bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom 1795bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom return ret; 1805bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom} 1815bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom 1825bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom 183fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzstatic int vmw_resource_init(struct vmw_private *dev_priv, 184fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_resource *res, 185fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct idr *idr, 186fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz enum ttm_object_type obj_type, 1875bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom bool delay_id, 1885bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom void (*res_free) (struct vmw_resource *res), 1895bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom void (*remove_from_lists) 1905bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom (struct vmw_resource *res)) 191fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 192fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz kref_init(&res->kref); 193fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz res->hw_destroy = NULL; 194fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz res->res_free = res_free; 1955bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom res->remove_from_lists = remove_from_lists; 196fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz res->res_type = obj_type; 197fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz res->idr = idr; 198fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz res->avail = false; 199fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz res->dev_priv = dev_priv; 200e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom INIT_LIST_HEAD(&res->query_head); 201f18c8840bef4195e6f35298b7746563f10d2d502Thomas Hellstrom INIT_LIST_HEAD(&res->validate_head); 2025bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom res->id = -1; 2035bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom if (delay_id) 2045bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom return 0; 2055bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom else 2065bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom return vmw_resource_alloc_id(dev_priv, res); 207fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 208fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 209fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz/** 210fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * vmw_resource_activate 211fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * 212fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * @res: Pointer to the newly created resource 213fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * @hw_destroy: Destroy function. NULL if none. 214fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * 215fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * Activate a resource after the hardware has been made aware of it. 216fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * Set tye destroy function to @destroy. Typically this frees the 217fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * resource and destroys the hardware resources associated with it. 218fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * Activate basically means that the function vmw_resource_lookup will 219fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * find it. 220fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz */ 221fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 222fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzstatic void vmw_resource_activate(struct vmw_resource *res, 223fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz void (*hw_destroy) (struct vmw_resource *)) 224fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 225fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_private *dev_priv = res->dev_priv; 226fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 227fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz write_lock(&dev_priv->resource_lock); 228fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz res->avail = true; 229fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz res->hw_destroy = hw_destroy; 230fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz write_unlock(&dev_priv->resource_lock); 231fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 232fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 233fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzstruct vmw_resource *vmw_resource_lookup(struct vmw_private *dev_priv, 234fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct idr *idr, int id) 235fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 236fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_resource *res; 237fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 238fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz read_lock(&dev_priv->resource_lock); 239fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz res = idr_find(idr, id); 240fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (res && res->avail) 241fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz kref_get(&res->kref); 242fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz else 243fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz res = NULL; 244fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz read_unlock(&dev_priv->resource_lock); 245fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 246fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (unlikely(res == NULL)) 247fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return NULL; 248fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 249fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return res; 250fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 251fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 252fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz/** 253fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * Context management: 254fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz */ 255fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 256fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzstatic void vmw_hw_context_destroy(struct vmw_resource *res) 257fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 258fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 259fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_private *dev_priv = res->dev_priv; 260fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct { 261fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz SVGA3dCmdHeader header; 262fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz SVGA3dCmdDestroyContext body; 263e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom } *cmd; 264e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom 265e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom 266e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom vmw_execbuf_release_pinned_bo(dev_priv, true, res->id); 267fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 268e2fa3a76839ada0d788549607263a036aa654243Thomas Hellstrom cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd)); 269fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (unlikely(cmd == NULL)) { 270fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz DRM_ERROR("Failed reserving FIFO space for surface " 271fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz "destruction.\n"); 272fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return; 273fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz } 274fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 275fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz cmd->header.id = cpu_to_le32(SVGA_3D_CMD_CONTEXT_DESTROY); 276fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz cmd->header.size = cpu_to_le32(sizeof(cmd->body)); 277fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz cmd->body.cid = cpu_to_le32(res->id); 278fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 279fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz vmw_fifo_commit(dev_priv, sizeof(*cmd)); 28005730b32a78dab4bed8fb7ccc64c53d9fcf31e9dThomas Hellstrom vmw_3d_resource_dec(dev_priv, false); 281fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 282fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 283fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzstatic int vmw_context_init(struct vmw_private *dev_priv, 284fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_resource *res, 285fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz void (*res_free) (struct vmw_resource *res)) 286fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 287fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz int ret; 288fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 289fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct { 290fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz SVGA3dCmdHeader header; 291fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz SVGA3dCmdDefineContext body; 292fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz } *cmd; 293fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 294fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ret = vmw_resource_init(dev_priv, res, &dev_priv->context_idr, 2955bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom VMW_RES_CONTEXT, false, res_free, NULL); 296fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 297fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (unlikely(ret != 0)) { 2985bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom DRM_ERROR("Failed to allocate a resource id.\n"); 2995bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom goto out_early; 3005bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom } 3015bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom 3025bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom if (unlikely(res->id >= SVGA3D_MAX_CONTEXT_IDS)) { 3035bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom DRM_ERROR("Out of hw context ids.\n"); 3045bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom vmw_resource_unreference(&res); 3055bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom return -ENOMEM; 306fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz } 307fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 308fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd)); 309fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (unlikely(cmd == NULL)) { 310fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz DRM_ERROR("Fifo reserve failed.\n"); 311fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz vmw_resource_unreference(&res); 312fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return -ENOMEM; 313fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz } 314fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 315fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz cmd->header.id = cpu_to_le32(SVGA_3D_CMD_CONTEXT_DEFINE); 316fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz cmd->header.size = cpu_to_le32(sizeof(cmd->body)); 317fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz cmd->body.cid = cpu_to_le32(res->id); 318fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 319fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz vmw_fifo_commit(dev_priv, sizeof(*cmd)); 32005730b32a78dab4bed8fb7ccc64c53d9fcf31e9dThomas Hellstrom (void) vmw_3d_resource_inc(dev_priv, false); 321fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz vmw_resource_activate(res, vmw_hw_context_destroy); 322fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return 0; 3235bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom 3245bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstromout_early: 3255bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom if (res_free == NULL) 3265bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom kfree(res); 3275bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom else 3285bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom res_free(res); 3295bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom return ret; 330fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 331fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 332fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzstruct vmw_resource *vmw_context_alloc(struct vmw_private *dev_priv) 333fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 334fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_resource *res = kmalloc(sizeof(*res), GFP_KERNEL); 335fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz int ret; 336fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 337fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (unlikely(res == NULL)) 338fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return NULL; 339fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 340fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ret = vmw_context_init(dev_priv, res, NULL); 341fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return (ret == 0) ? res : NULL; 342fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 343fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 344fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz/** 345fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * User-space context management: 346fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz */ 347fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 348fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzstatic void vmw_user_context_free(struct vmw_resource *res) 349fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 350fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_user_context *ctx = 351fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz container_of(res, struct vmw_user_context, res); 352414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom struct vmw_private *dev_priv = res->dev_priv; 353fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 354fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz kfree(ctx); 355414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom ttm_mem_global_free(vmw_mem_glob(dev_priv), 356414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom vmw_user_context_size); 357fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 358fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 359fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz/** 360fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * This function is called when user space has no more references on the 361fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * base object. It releases the base-object's reference on the resource object. 362fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz */ 363fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 364fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzstatic void vmw_user_context_base_release(struct ttm_base_object **p_base) 365fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 366fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct ttm_base_object *base = *p_base; 367fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_user_context *ctx = 368fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz container_of(base, struct vmw_user_context, base); 369fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_resource *res = &ctx->res; 370fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 371fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz *p_base = NULL; 372fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz vmw_resource_unreference(&res); 373fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 374fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 375fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzint vmw_context_destroy_ioctl(struct drm_device *dev, void *data, 376fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct drm_file *file_priv) 377fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 378fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_private *dev_priv = vmw_priv(dev); 379fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_resource *res; 380fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_user_context *ctx; 381fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct drm_vmw_context_arg *arg = (struct drm_vmw_context_arg *)data; 382fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile; 383fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz int ret = 0; 384fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 385fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz res = vmw_resource_lookup(dev_priv, &dev_priv->context_idr, arg->cid); 386fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (unlikely(res == NULL)) 387fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return -EINVAL; 388fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 389fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (res->res_free != &vmw_user_context_free) { 390fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ret = -EINVAL; 391fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz goto out; 392fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz } 393fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 394fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ctx = container_of(res, struct vmw_user_context, res); 395fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (ctx->base.tfile != tfile && !ctx->base.shareable) { 396fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ret = -EPERM; 397fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz goto out; 398fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz } 399fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 400fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ttm_ref_object_base_unref(tfile, ctx->base.hash.key, TTM_REF_USAGE); 401fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzout: 402fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz vmw_resource_unreference(&res); 403fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return ret; 404fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 405fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 406fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzint vmw_context_define_ioctl(struct drm_device *dev, void *data, 407fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct drm_file *file_priv) 408fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 409fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_private *dev_priv = vmw_priv(dev); 410414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom struct vmw_user_context *ctx; 411fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_resource *res; 412fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_resource *tmp; 413fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct drm_vmw_context_arg *arg = (struct drm_vmw_context_arg *)data; 414fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile; 415414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom struct vmw_master *vmaster = vmw_master(file_priv->master); 416fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz int ret; 417fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 418414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom 419414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom /* 420414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom * Approximate idr memory usage with 128 bytes. It will be limited 421414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom * by maximum number_of contexts anyway. 422414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom */ 423414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom 424414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom if (unlikely(vmw_user_context_size == 0)) 425414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom vmw_user_context_size = ttm_round_pot(sizeof(*ctx)) + 128; 426414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom 427414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom ret = ttm_read_lock(&vmaster->lock, true); 428414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom if (unlikely(ret != 0)) 429414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom return ret; 430414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom 431414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom ret = ttm_mem_global_alloc(vmw_mem_glob(dev_priv), 432414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom vmw_user_context_size, 433414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom false, true); 434414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom if (unlikely(ret != 0)) { 435414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom if (ret != -ERESTARTSYS) 436414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom DRM_ERROR("Out of graphics memory for context" 437414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom " creation.\n"); 438414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom goto out_unlock; 439414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom } 440414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom 441414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom ctx = kmalloc(sizeof(*ctx), GFP_KERNEL); 442414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom if (unlikely(ctx == NULL)) { 443414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom ttm_mem_global_free(vmw_mem_glob(dev_priv), 444414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom vmw_user_context_size); 445414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom ret = -ENOMEM; 446414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom goto out_unlock; 447414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom } 448fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 449fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz res = &ctx->res; 450fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ctx->base.shareable = false; 451fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ctx->base.tfile = NULL; 452fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 453414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom /* 454414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom * From here on, the destructor takes over resource freeing. 455414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom */ 456414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom 457fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ret = vmw_context_init(dev_priv, res, vmw_user_context_free); 458fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (unlikely(ret != 0)) 459414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom goto out_unlock; 460fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 461fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz tmp = vmw_resource_reference(&ctx->res); 462fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ret = ttm_base_object_init(tfile, &ctx->base, false, VMW_RES_CONTEXT, 463fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz &vmw_user_context_base_release, NULL); 464fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 465fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (unlikely(ret != 0)) { 466fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz vmw_resource_unreference(&tmp); 467fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz goto out_err; 468fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz } 469fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 470fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz arg->cid = res->id; 471fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzout_err: 472fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz vmw_resource_unreference(&res); 473414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstromout_unlock: 474414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom ttm_read_unlock(&vmaster->lock); 475fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return ret; 476fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 477fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 478fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 479fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzint vmw_context_check(struct vmw_private *dev_priv, 480fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct ttm_object_file *tfile, 481be38ab6ea7b0de0542a0ff78690d63bb22f66a4dThomas Hellstrom int id, 482be38ab6ea7b0de0542a0ff78690d63bb22f66a4dThomas Hellstrom struct vmw_resource **p_res) 483fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 484fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_resource *res; 485fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz int ret = 0; 486fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 487fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz read_lock(&dev_priv->resource_lock); 488fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz res = idr_find(&dev_priv->context_idr, id); 489fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (res && res->avail) { 490fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_user_context *ctx = 491fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz container_of(res, struct vmw_user_context, res); 492fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (ctx->base.tfile != tfile && !ctx->base.shareable) 493fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ret = -EPERM; 494be38ab6ea7b0de0542a0ff78690d63bb22f66a4dThomas Hellstrom if (p_res) 495be38ab6ea7b0de0542a0ff78690d63bb22f66a4dThomas Hellstrom *p_res = vmw_resource_reference(res); 496fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz } else 497fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ret = -EINVAL; 498fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz read_unlock(&dev_priv->resource_lock); 499fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 500fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return ret; 501fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 502fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 5035bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstromstruct vmw_bpp { 5045bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom uint8_t bpp; 5055bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom uint8_t s_bpp; 5065bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom}; 5075bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom 5085bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom/* 5095bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom * Size table for the supported SVGA3D surface formats. It consists of 5105bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom * two values. The bpp value and the s_bpp value which is short for 5115bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom * "stride bits per pixel" The values are given in such a way that the 5125bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom * minimum stride for the image is calculated using 5135bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom * 5145bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom * min_stride = w*s_bpp 5155bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom * 5165bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom * and the total memory requirement for the image is 5175bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom * 5185bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom * h*min_stride*bpp/s_bpp 5195bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom * 5205bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom */ 5215bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstromstatic const struct vmw_bpp vmw_sf_bpp[] = { 5225bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom [SVGA3D_FORMAT_INVALID] = {0, 0}, 5235bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom [SVGA3D_X8R8G8B8] = {32, 32}, 5245bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom [SVGA3D_A8R8G8B8] = {32, 32}, 5255bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom [SVGA3D_R5G6B5] = {16, 16}, 5265bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom [SVGA3D_X1R5G5B5] = {16, 16}, 5275bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom [SVGA3D_A1R5G5B5] = {16, 16}, 5285bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom [SVGA3D_A4R4G4B4] = {16, 16}, 5295bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom [SVGA3D_Z_D32] = {32, 32}, 5305bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom [SVGA3D_Z_D16] = {16, 16}, 5315bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom [SVGA3D_Z_D24S8] = {32, 32}, 5325bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom [SVGA3D_Z_D15S1] = {16, 16}, 5335bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom [SVGA3D_LUMINANCE8] = {8, 8}, 5345bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom [SVGA3D_LUMINANCE4_ALPHA4] = {8, 8}, 5355bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom [SVGA3D_LUMINANCE16] = {16, 16}, 5365bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom [SVGA3D_LUMINANCE8_ALPHA8] = {16, 16}, 5375bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom [SVGA3D_DXT1] = {4, 16}, 5385bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom [SVGA3D_DXT2] = {8, 32}, 5395bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom [SVGA3D_DXT3] = {8, 32}, 5405bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom [SVGA3D_DXT4] = {8, 32}, 5415bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom [SVGA3D_DXT5] = {8, 32}, 5425bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom [SVGA3D_BUMPU8V8] = {16, 16}, 5435bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom [SVGA3D_BUMPL6V5U5] = {16, 16}, 5445bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom [SVGA3D_BUMPX8L8V8U8] = {32, 32}, 5455bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom [SVGA3D_ARGB_S10E5] = {16, 16}, 5465bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom [SVGA3D_ARGB_S23E8] = {32, 32}, 5475bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom [SVGA3D_A2R10G10B10] = {32, 32}, 5485bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom [SVGA3D_V8U8] = {16, 16}, 5495bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom [SVGA3D_Q8W8V8U8] = {32, 32}, 5505bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom [SVGA3D_CxV8U8] = {16, 16}, 5515bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom [SVGA3D_X8L8V8U8] = {32, 32}, 5525bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom [SVGA3D_A2W10V10U10] = {32, 32}, 5535bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom [SVGA3D_ALPHA8] = {8, 8}, 5545bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom [SVGA3D_R_S10E5] = {16, 16}, 5555bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom [SVGA3D_R_S23E8] = {32, 32}, 5565bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom [SVGA3D_RG_S10E5] = {16, 16}, 5575bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom [SVGA3D_RG_S23E8] = {32, 32}, 5585bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom [SVGA3D_BUFFER] = {8, 8}, 5595bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom [SVGA3D_Z_D24X8] = {32, 32}, 5605bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom [SVGA3D_V16U16] = {32, 32}, 5615bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom [SVGA3D_G16R16] = {32, 32}, 5625bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom [SVGA3D_A16B16G16R16] = {64, 64}, 5635bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom [SVGA3D_UYVY] = {12, 12}, 5645bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom [SVGA3D_YUY2] = {12, 12}, 5655bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom [SVGA3D_NV12] = {12, 8}, 5665bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom [SVGA3D_AYUV] = {32, 32}, 5675bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom [SVGA3D_BC4_UNORM] = {4, 16}, 5685bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom [SVGA3D_BC5_UNORM] = {8, 32}, 5695bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom [SVGA3D_Z_DF16] = {16, 16}, 5705bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom [SVGA3D_Z_DF24] = {24, 24}, 5715bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom [SVGA3D_Z_D24S8_INT] = {32, 32} 5725bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom}; 5735bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom 574fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 575fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz/** 576fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * Surface management. 577fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz */ 578fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 5795bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstromstruct vmw_surface_dma { 5805bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom SVGA3dCmdHeader header; 5815bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom SVGA3dCmdSurfaceDMA body; 5825bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom SVGA3dCopyBox cb; 5835bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom SVGA3dCmdSurfaceDMASuffix suffix; 5845bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom}; 5855bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom 5865bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstromstruct vmw_surface_define { 5875bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom SVGA3dCmdHeader header; 5885bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom SVGA3dCmdDefineSurface body; 5895bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom}; 5905bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom 5915bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstromstruct vmw_surface_destroy { 5925bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom SVGA3dCmdHeader header; 5935bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom SVGA3dCmdDestroySurface body; 5945bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom}; 5955bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom 5965bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom 5975bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom/** 5985bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom * vmw_surface_dma_size - Compute fifo size for a dma command. 5995bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom * 6005bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom * @srf: Pointer to a struct vmw_surface 6015bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom * 6025bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom * Computes the required size for a surface dma command for backup or 6035bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom * restoration of the surface represented by @srf. 6045bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom */ 6055bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstromstatic inline uint32_t vmw_surface_dma_size(const struct vmw_surface *srf) 6065bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom{ 6075bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom return srf->num_sizes * sizeof(struct vmw_surface_dma); 6085bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom} 6095bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom 6105bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom 6115bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom/** 6125bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom * vmw_surface_define_size - Compute fifo size for a surface define command. 6135bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom * 6145bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom * @srf: Pointer to a struct vmw_surface 6155bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom * 6165bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom * Computes the required size for a surface define command for the definition 6175bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom * of the surface represented by @srf. 6185bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom */ 6195bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstromstatic inline uint32_t vmw_surface_define_size(const struct vmw_surface *srf) 6205bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom{ 6215bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom return sizeof(struct vmw_surface_define) + srf->num_sizes * 6225bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom sizeof(SVGA3dSize); 6235bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom} 6245bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom 6255bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom 6265bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom/** 6275bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom * vmw_surface_destroy_size - Compute fifo size for a surface destroy command. 6285bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom * 6295bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom * Computes the required size for a surface destroy command for the destruction 6305bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom * of a hw surface. 6315bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom */ 6325bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstromstatic inline uint32_t vmw_surface_destroy_size(void) 6335bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom{ 6345bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom return sizeof(struct vmw_surface_destroy); 6355bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom} 6365bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom 6375bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom/** 6385bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom * vmw_surface_destroy_encode - Encode a surface_destroy command. 6395bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom * 6405bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom * @id: The surface id 6415bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom * @cmd_space: Pointer to memory area in which the commands should be encoded. 6425bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom */ 6435bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstromstatic void vmw_surface_destroy_encode(uint32_t id, 6445bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom void *cmd_space) 6455bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom{ 6465bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom struct vmw_surface_destroy *cmd = (struct vmw_surface_destroy *) 6475bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom cmd_space; 6485bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom 6495bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom cmd->header.id = SVGA_3D_CMD_SURFACE_DESTROY; 6505bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom cmd->header.size = sizeof(cmd->body); 6515bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom cmd->body.sid = id; 6525bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom} 6535bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom 6545bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom/** 6555bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom * vmw_surface_define_encode - Encode a surface_define command. 6565bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom * 6575bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom * @srf: Pointer to a struct vmw_surface object. 6585bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom * @cmd_space: Pointer to memory area in which the commands should be encoded. 6595bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom */ 6605bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstromstatic void vmw_surface_define_encode(const struct vmw_surface *srf, 6615bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom void *cmd_space) 6625bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom{ 6635bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom struct vmw_surface_define *cmd = (struct vmw_surface_define *) 6645bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom cmd_space; 6655bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom struct drm_vmw_size *src_size; 6665bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom SVGA3dSize *cmd_size; 6675bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom uint32_t cmd_len; 6685bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom int i; 6695bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom 6705bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom cmd_len = sizeof(cmd->body) + srf->num_sizes * sizeof(SVGA3dSize); 6715bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom 6725bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom cmd->header.id = SVGA_3D_CMD_SURFACE_DEFINE; 6735bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom cmd->header.size = cmd_len; 6745bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom cmd->body.sid = srf->res.id; 6755bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom cmd->body.surfaceFlags = srf->flags; 6765bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom cmd->body.format = cpu_to_le32(srf->format); 6775bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom for (i = 0; i < DRM_VMW_MAX_SURFACE_FACES; ++i) 6785bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom cmd->body.face[i].numMipLevels = srf->mip_levels[i]; 6795bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom 6805bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom cmd += 1; 6815bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom cmd_size = (SVGA3dSize *) cmd; 6825bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom src_size = srf->sizes; 6835bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom 6845bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom for (i = 0; i < srf->num_sizes; ++i, cmd_size++, src_size++) { 6855bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom cmd_size->width = src_size->width; 6865bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom cmd_size->height = src_size->height; 6875bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom cmd_size->depth = src_size->depth; 6885bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom } 6895bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom} 6905bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom 6915bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom 6925bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom/** 6935bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom * vmw_surface_dma_encode - Encode a surface_dma command. 6945bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom * 6955bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom * @srf: Pointer to a struct vmw_surface object. 6965bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom * @cmd_space: Pointer to memory area in which the commands should be encoded. 6975bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom * @ptr: Pointer to an SVGAGuestPtr indicating where the surface contents 6985bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom * should be placed or read from. 6995bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom * @to_surface: Boolean whether to DMA to the surface or from the surface. 7005bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom */ 7015bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstromstatic void vmw_surface_dma_encode(struct vmw_surface *srf, 7025bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom void *cmd_space, 7035bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom const SVGAGuestPtr *ptr, 7045bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom bool to_surface) 7055bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom{ 7065bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom uint32_t i; 7075bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom uint32_t bpp = vmw_sf_bpp[srf->format].bpp; 7085bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom uint32_t stride_bpp = vmw_sf_bpp[srf->format].s_bpp; 7095bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom struct vmw_surface_dma *cmd = (struct vmw_surface_dma *)cmd_space; 7105bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom 7115bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom for (i = 0; i < srf->num_sizes; ++i) { 7125bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom SVGA3dCmdHeader *header = &cmd->header; 7135bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom SVGA3dCmdSurfaceDMA *body = &cmd->body; 7145bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom SVGA3dCopyBox *cb = &cmd->cb; 7155bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom SVGA3dCmdSurfaceDMASuffix *suffix = &cmd->suffix; 7165bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom const struct vmw_surface_offset *cur_offset = &srf->offsets[i]; 7175bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom const struct drm_vmw_size *cur_size = &srf->sizes[i]; 7185bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom 7195bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom header->id = SVGA_3D_CMD_SURFACE_DMA; 7205bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom header->size = sizeof(*body) + sizeof(*cb) + sizeof(*suffix); 7215bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom 7225bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom body->guest.ptr = *ptr; 7235bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom body->guest.ptr.offset += cur_offset->bo_offset; 7245bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom body->guest.pitch = (cur_size->width * stride_bpp + 7) >> 3; 7255bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom body->host.sid = srf->res.id; 7265bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom body->host.face = cur_offset->face; 7275bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom body->host.mipmap = cur_offset->mip; 7285bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom body->transfer = ((to_surface) ? SVGA3D_WRITE_HOST_VRAM : 7295bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom SVGA3D_READ_HOST_VRAM); 7305bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom cb->x = 0; 7315bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom cb->y = 0; 7325bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom cb->z = 0; 7335bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom cb->srcx = 0; 7345bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom cb->srcy = 0; 7355bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom cb->srcz = 0; 7365bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom cb->w = cur_size->width; 7375bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom cb->h = cur_size->height; 7385bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom cb->d = cur_size->depth; 7395bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom 7405bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom suffix->suffixSize = sizeof(*suffix); 7415bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom suffix->maximumOffset = body->guest.pitch*cur_size->height* 7425bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom cur_size->depth*bpp / stride_bpp; 7435bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom suffix->flags.discard = 0; 7445bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom suffix->flags.unsynchronized = 0; 7455bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom suffix->flags.reserved = 0; 7465bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom ++cmd; 7475bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom } 7485bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom}; 7495bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom 7505bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom 751fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzstatic void vmw_hw_surface_destroy(struct vmw_resource *res) 752fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 753fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 754fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_private *dev_priv = res->dev_priv; 7555bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom struct vmw_surface *srf; 7565bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom void *cmd; 757fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 7585bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom if (res->id != -1) { 759fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 7605bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom cmd = vmw_fifo_reserve(dev_priv, vmw_surface_destroy_size()); 7615bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom if (unlikely(cmd == NULL)) { 7625bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom DRM_ERROR("Failed reserving FIFO space for surface " 7635bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom "destruction.\n"); 7645bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom return; 7655bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom } 766fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 7675bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom vmw_surface_destroy_encode(res->id, cmd); 7685bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom vmw_fifo_commit(dev_priv, vmw_surface_destroy_size()); 7695bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom 7705bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom /* 7715bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom * used_memory_size_atomic, or separate lock 7725bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom * to avoid taking dev_priv::cmdbuf_mutex in 7735bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom * the destroy path. 7745bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom */ 7755bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom 7765bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom mutex_lock(&dev_priv->cmdbuf_mutex); 7775bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom srf = container_of(res, struct vmw_surface, res); 7785bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom dev_priv->used_memory_size -= srf->backup_size; 7795bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom mutex_unlock(&dev_priv->cmdbuf_mutex); 7805bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom 7815bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom } 78205730b32a78dab4bed8fb7ccc64c53d9fcf31e9dThomas Hellstrom vmw_3d_resource_dec(dev_priv, false); 783fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 784fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 785fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzvoid vmw_surface_res_free(struct vmw_resource *res) 786fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 787fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_surface *srf = container_of(res, struct vmw_surface, res); 788fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 7895bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom if (srf->backup) 7905bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom ttm_bo_unref(&srf->backup); 7915bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom kfree(srf->offsets); 792fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz kfree(srf->sizes); 793fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz kfree(srf->snooper.image); 794fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz kfree(srf); 795fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 796fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 7975bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom 7985bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom/** 7995bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom * vmw_surface_do_validate - make a surface available to the device. 8005bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom * 8015bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom * @dev_priv: Pointer to a device private struct. 8025bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom * @srf: Pointer to a struct vmw_surface. 8035bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom * 8045bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom * If the surface doesn't have a hw id, allocate one, and optionally 8055bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom * DMA the backed up surface contents to the device. 8065bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom * 8075bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom * Returns -EBUSY if there wasn't sufficient device resources to 8085bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom * complete the validation. Retry after freeing up resources. 8095bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom * 8105bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom * May return other errors if the kernel is out of guest resources. 8115bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom */ 8125bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstromint vmw_surface_do_validate(struct vmw_private *dev_priv, 8135bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom struct vmw_surface *srf) 814fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 815fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_resource *res = &srf->res; 8165bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom struct list_head val_list; 8175bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom struct ttm_validate_buffer val_buf; 8185bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom uint32_t submit_size; 8195bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom uint8_t *cmd; 8205bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom int ret; 821fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 8225bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom if (likely(res->id != -1)) 8235bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom return 0; 8245bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom 8255bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom if (unlikely(dev_priv->used_memory_size + srf->backup_size >= 8265bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom dev_priv->memory_size)) 8275bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom return -EBUSY; 8285bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom 8295bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom /* 8305bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom * Reserve- and validate the backup DMA bo. 8315bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom */ 8325bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom 8335bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom if (srf->backup) { 8345bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom INIT_LIST_HEAD(&val_list); 8355bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom val_buf.bo = ttm_bo_reference(srf->backup); 8365bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom val_buf.new_sync_obj_arg = (void *)((unsigned long) 8375bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom DRM_VMW_FENCE_FLAG_EXEC); 8385bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom list_add_tail(&val_buf.head, &val_list); 8395bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom ret = ttm_eu_reserve_buffers(&val_list); 8405bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom if (unlikely(ret != 0)) 8415bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom goto out_no_reserve; 8425bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom 8435bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom ret = ttm_bo_validate(srf->backup, &vmw_srf_placement, 8445bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom true, false, false); 8455bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom if (unlikely(ret != 0)) 8465bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom goto out_no_validate; 8475bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom } 8485bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom 8495bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom /* 8505bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom * Alloc id for the resource. 8515bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom */ 852fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 8535bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom ret = vmw_resource_alloc_id(dev_priv, res); 854fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (unlikely(ret != 0)) { 8555bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom DRM_ERROR("Failed to allocate a surface id.\n"); 8565bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom goto out_no_id; 8575bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom } 8585bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom if (unlikely(res->id >= SVGA3D_MAX_SURFACE_IDS)) { 8595bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom ret = -EBUSY; 8605bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom goto out_no_fifo; 861fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz } 862fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 8635bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom 8645bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom /* 8655bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom * Encode surface define- and dma commands. 8665bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom */ 8675bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom 8685bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom submit_size = vmw_surface_define_size(srf); 8695bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom if (srf->backup) 8705bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom submit_size += vmw_surface_dma_size(srf); 871fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 872fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz cmd = vmw_fifo_reserve(dev_priv, submit_size); 873fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (unlikely(cmd == NULL)) { 8745bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom DRM_ERROR("Failed reserving FIFO space for surface " 8755bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom "validation.\n"); 8765bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom ret = -ENOMEM; 8775bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom goto out_no_fifo; 878fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz } 879fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 8805bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom vmw_surface_define_encode(srf, cmd); 8815bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom if (srf->backup) { 8825bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom SVGAGuestPtr ptr; 8835bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom 8845bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom cmd += vmw_surface_define_size(srf); 8855bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom vmw_bo_get_guest_ptr(srf->backup, &ptr); 8865bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom vmw_surface_dma_encode(srf, cmd, &ptr, true); 887fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz } 888fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 8895bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom vmw_fifo_commit(dev_priv, submit_size); 890fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 8915bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom /* 8925bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom * Create a fence object and fence the backup buffer. 8935bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom */ 8945bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom 8955bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom if (srf->backup) { 8965bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom struct vmw_fence_obj *fence; 8975bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom 8985bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom (void) vmw_execbuf_fence_commands(NULL, dev_priv, 8995bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom &fence, NULL); 9005bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom ttm_eu_fence_buffer_objects(&val_list, fence); 9015bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom if (likely(fence != NULL)) 9025bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom vmw_fence_obj_unreference(&fence); 9035bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom ttm_bo_unref(&val_buf.bo); 9045bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom ttm_bo_unref(&srf->backup); 905fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz } 906fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 9075bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom /* 9085bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom * Surface memory usage accounting. 9095bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom */ 9105bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom 9115bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom dev_priv->used_memory_size += srf->backup_size; 9125bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom 9135bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom return 0; 9145bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom 9155bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstromout_no_fifo: 9165bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom vmw_resource_release_id(res); 9175bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstromout_no_id: 9185bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstromout_no_validate: 9195bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom if (srf->backup) 9205bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom ttm_eu_backoff_reservation(&val_list); 9215bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstromout_no_reserve: 9225bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom if (srf->backup) 9235bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom ttm_bo_unref(&val_buf.bo); 9245bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom return ret; 9255bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom} 9265bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom 9275bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom/** 9285bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom * vmw_surface_evict - Evict a hw surface. 9295bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom * 9305bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom * @dev_priv: Pointer to a device private struct. 9315bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom * @srf: Pointer to a struct vmw_surface 9325bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom * 9335bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom * DMA the contents of a hw surface to a backup guest buffer object, 9345bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom * and destroy the hw surface, releasing its id. 9355bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom */ 9365bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstromint vmw_surface_evict(struct vmw_private *dev_priv, 9375bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom struct vmw_surface *srf) 9385bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom{ 9395bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom struct vmw_resource *res = &srf->res; 9405bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom struct list_head val_list; 9415bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom struct ttm_validate_buffer val_buf; 9425bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom uint32_t submit_size; 9435bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom uint8_t *cmd; 9445bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom int ret; 9455bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom struct vmw_fence_obj *fence; 9465bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom SVGAGuestPtr ptr; 9475bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom 9485bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom BUG_ON(res->id == -1); 9495bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom 9505bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom /* 9515bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom * Create a surface backup buffer object. 9525bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom */ 9535bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom 9545bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom if (!srf->backup) { 9555bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom ret = ttm_bo_create(&dev_priv->bdev, srf->backup_size, 9565bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom ttm_bo_type_device, 9575bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom &vmw_srf_placement, 0, 0, true, 9585bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom NULL, &srf->backup); 9595bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom if (unlikely(ret != 0)) 9605bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom return ret; 9615bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom } 9625bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom 9635bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom /* 9645bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom * Reserve- and validate the backup DMA bo. 9655bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom */ 9665bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom 9675bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom INIT_LIST_HEAD(&val_list); 9685bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom val_buf.bo = ttm_bo_reference(srf->backup); 9695bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom val_buf.new_sync_obj_arg = (void *)(unsigned long) 9705bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom DRM_VMW_FENCE_FLAG_EXEC; 9715bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom list_add_tail(&val_buf.head, &val_list); 9725bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom ret = ttm_eu_reserve_buffers(&val_list); 9735bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom if (unlikely(ret != 0)) 9745bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom goto out_no_reserve; 9755bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom 9765bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom ret = ttm_bo_validate(srf->backup, &vmw_srf_placement, 9775bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom true, false, false); 9785bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom if (unlikely(ret != 0)) 9795bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom goto out_no_validate; 9805bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom 9815bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom 9825bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom /* 9835bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom * Encode the dma- and surface destroy commands. 9845bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom */ 9855bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom 9865bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom submit_size = vmw_surface_dma_size(srf) + vmw_surface_destroy_size(); 9875bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom cmd = vmw_fifo_reserve(dev_priv, submit_size); 9885bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom if (unlikely(cmd == NULL)) { 9895bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom DRM_ERROR("Failed reserving FIFO space for surface " 9905bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom "eviction.\n"); 9915bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom ret = -ENOMEM; 9925bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom goto out_no_fifo; 9935bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom } 9945bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom 9955bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom vmw_bo_get_guest_ptr(srf->backup, &ptr); 9965bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom vmw_surface_dma_encode(srf, cmd, &ptr, false); 9975bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom cmd += vmw_surface_dma_size(srf); 9985bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom vmw_surface_destroy_encode(res->id, cmd); 999fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz vmw_fifo_commit(dev_priv, submit_size); 10005bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom 10015bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom /* 10025bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom * Surface memory usage accounting. 10035bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom */ 10045bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom 10055bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom dev_priv->used_memory_size -= srf->backup_size; 10065bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom 10075bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom /* 10085bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom * Create a fence object and fence the DMA buffer. 10095bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom */ 10105bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom 10115bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom (void) vmw_execbuf_fence_commands(NULL, dev_priv, 10125bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom &fence, NULL); 10135bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom ttm_eu_fence_buffer_objects(&val_list, fence); 10145bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom if (likely(fence != NULL)) 10155bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom vmw_fence_obj_unreference(&fence); 10165bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom ttm_bo_unref(&val_buf.bo); 10175bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom 10185bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom /* 10195bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom * Release the surface ID. 10205bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom */ 10215bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom 10225bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom vmw_resource_release_id(res); 10235bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom 10245bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom return 0; 10255bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom 10265bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstromout_no_fifo: 10275bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstromout_no_validate: 10285bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom if (srf->backup) 10295bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom ttm_eu_backoff_reservation(&val_list); 10305bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstromout_no_reserve: 10315bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom ttm_bo_unref(&val_buf.bo); 10325bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom ttm_bo_unref(&srf->backup); 10335bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom return ret; 10345bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom} 10355bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom 10365bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom 10375bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom/** 10385bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom * vmw_surface_validate - make a surface available to the device, evicting 10395bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom * other surfaces if needed. 10405bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom * 10415bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom * @dev_priv: Pointer to a device private struct. 10425bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom * @srf: Pointer to a struct vmw_surface. 10435bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom * 10445bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom * Try to validate a surface and if it fails due to limited device resources, 10455bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom * repeatedly try to evict other surfaces until the request can be 10465bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom * acommodated. 10475bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom * 10485bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom * May return errors if out of resources. 10495bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom */ 10505bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstromint vmw_surface_validate(struct vmw_private *dev_priv, 10515bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom struct vmw_surface *srf) 10525bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom{ 10535bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom int ret; 10545bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom struct vmw_surface *evict_srf; 10555bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom 10565bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom do { 10575bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom write_lock(&dev_priv->resource_lock); 10585bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom list_del_init(&srf->lru_head); 10595bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom write_unlock(&dev_priv->resource_lock); 10605bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom 10615bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom ret = vmw_surface_do_validate(dev_priv, srf); 10625bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom if (likely(ret != -EBUSY)) 10635bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom break; 10645bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom 10655bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom write_lock(&dev_priv->resource_lock); 10665bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom if (list_empty(&dev_priv->surface_lru)) { 10675bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom DRM_ERROR("Out of device memory for surfaces.\n"); 10685bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom ret = -EBUSY; 10695bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom write_unlock(&dev_priv->resource_lock); 10705bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom break; 10715bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom } 10725bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom 10735bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom evict_srf = vmw_surface_reference 10745bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom (list_first_entry(&dev_priv->surface_lru, 10755bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom struct vmw_surface, 10765bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom lru_head)); 10775bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom list_del_init(&evict_srf->lru_head); 10785bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom 10795bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom write_unlock(&dev_priv->resource_lock); 10805bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom (void) vmw_surface_evict(dev_priv, evict_srf); 10815bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom 10825bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom vmw_surface_unreference(&evict_srf); 10835bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom 10845bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom } while (1); 10855bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom 10865bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom if (unlikely(ret != 0 && srf->res.id != -1)) { 10875bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom write_lock(&dev_priv->resource_lock); 10885bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom list_add_tail(&srf->lru_head, &dev_priv->surface_lru); 10895bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom write_unlock(&dev_priv->resource_lock); 10905bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom } 10915bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom 10925bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom return ret; 10935bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom} 10945bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom 10955bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom 10965bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom/** 10975bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom * vmw_surface_remove_from_lists - Remove surface resources from lookup lists 10985bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom * 10995bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom * @res: Pointer to a struct vmw_resource embedded in a struct vmw_surface 11005bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom * 11015bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom * As part of the resource destruction, remove the surface from any 11025bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom * lookup lists. 11035bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom */ 11045bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstromstatic void vmw_surface_remove_from_lists(struct vmw_resource *res) 11055bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom{ 11065bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom struct vmw_surface *srf = container_of(res, struct vmw_surface, res); 11075bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom 11085bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom list_del_init(&srf->lru_head); 11095bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom} 11105bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom 11115bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstromint vmw_surface_init(struct vmw_private *dev_priv, 11125bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom struct vmw_surface *srf, 11135bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom void (*res_free) (struct vmw_resource *res)) 11145bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom{ 11155bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom int ret; 11165bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom struct vmw_resource *res = &srf->res; 11175bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom 11185bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom BUG_ON(res_free == NULL); 11195bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom INIT_LIST_HEAD(&srf->lru_head); 11205bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom ret = vmw_resource_init(dev_priv, res, &dev_priv->surface_idr, 11215bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom VMW_RES_SURFACE, true, res_free, 11225bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom vmw_surface_remove_from_lists); 11235bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom 11245bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom if (unlikely(ret != 0)) 11255bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom res_free(res); 11265bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom 11275bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom /* 11285bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom * The surface won't be visible to hardware until a 11295bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom * surface validate. 11305bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom */ 11315bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom 113205730b32a78dab4bed8fb7ccc64c53d9fcf31e9dThomas Hellstrom (void) vmw_3d_resource_inc(dev_priv, false); 1133fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz vmw_resource_activate(res, vmw_hw_surface_destroy); 11345bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom return ret; 1135fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 1136fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1137fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzstatic void vmw_user_surface_free(struct vmw_resource *res) 1138fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 1139fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_surface *srf = container_of(res, struct vmw_surface, res); 1140fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_user_surface *user_srf = 1141fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz container_of(srf, struct vmw_user_surface, srf); 1142414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom struct vmw_private *dev_priv = srf->res.dev_priv; 1143414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom uint32_t size = user_srf->size; 1144fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 11455bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom if (srf->backup) 11465bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom ttm_bo_unref(&srf->backup); 11475bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom kfree(srf->offsets); 1148fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz kfree(srf->sizes); 1149fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz kfree(srf->snooper.image); 1150fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz kfree(user_srf); 1151414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom ttm_mem_global_free(vmw_mem_glob(dev_priv), size); 1152fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 1153fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 11545bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom/** 11555bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom * vmw_resource_unreserve - unreserve resources previously reserved for 11565bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom * command submission. 11575bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom * 11585bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom * @list_head: list of resources to unreserve. 11595bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom * 11605bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom * Currently only surfaces are considered, and unreserving a surface 11615bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom * means putting it back on the device's surface lru list, 11625bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom * so that it can be evicted if necessary. 11635bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom * This function traverses the resource list and 11645bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom * checks whether resources are surfaces, and in that case puts them back 11655bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom * on the device's surface LRU list. 11665bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom */ 11675bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstromvoid vmw_resource_unreserve(struct list_head *list) 11685bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom{ 11695bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom struct vmw_resource *res; 11705bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom struct vmw_surface *srf; 11715bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom rwlock_t *lock = NULL; 11725bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom 11735bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom list_for_each_entry(res, list, validate_head) { 11745bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom 11755bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom if (res->res_free != &vmw_surface_res_free && 11765bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom res->res_free != &vmw_user_surface_free) 11775bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom continue; 11785bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom 11795bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom if (unlikely(lock == NULL)) { 11805bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom lock = &res->dev_priv->resource_lock; 11815bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom write_lock(lock); 11825bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom } 11835bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom 11845bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom srf = container_of(res, struct vmw_surface, res); 11855bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom list_del_init(&srf->lru_head); 11865bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom list_add_tail(&srf->lru_head, &res->dev_priv->surface_lru); 11875bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom } 11885bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom 11895bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom if (lock != NULL) 11905bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom write_unlock(lock); 11915bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom} 11925bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom 1193551a6697d08f92a311d6adbf8d03af2bc7f9e2eeJakob Bornecrantz/** 1194551a6697d08f92a311d6adbf8d03af2bc7f9e2eeJakob Bornecrantz * Helper function that looks either a surface or dmabuf. 1195551a6697d08f92a311d6adbf8d03af2bc7f9e2eeJakob Bornecrantz * 1196551a6697d08f92a311d6adbf8d03af2bc7f9e2eeJakob Bornecrantz * The pointer this pointed at by out_surf and out_buf needs to be null. 1197551a6697d08f92a311d6adbf8d03af2bc7f9e2eeJakob Bornecrantz */ 1198551a6697d08f92a311d6adbf8d03af2bc7f9e2eeJakob Bornecrantzint vmw_user_lookup_handle(struct vmw_private *dev_priv, 1199551a6697d08f92a311d6adbf8d03af2bc7f9e2eeJakob Bornecrantz struct ttm_object_file *tfile, 1200551a6697d08f92a311d6adbf8d03af2bc7f9e2eeJakob Bornecrantz uint32_t handle, 1201551a6697d08f92a311d6adbf8d03af2bc7f9e2eeJakob Bornecrantz struct vmw_surface **out_surf, 1202551a6697d08f92a311d6adbf8d03af2bc7f9e2eeJakob Bornecrantz struct vmw_dma_buffer **out_buf) 1203551a6697d08f92a311d6adbf8d03af2bc7f9e2eeJakob Bornecrantz{ 1204551a6697d08f92a311d6adbf8d03af2bc7f9e2eeJakob Bornecrantz int ret; 1205551a6697d08f92a311d6adbf8d03af2bc7f9e2eeJakob Bornecrantz 1206551a6697d08f92a311d6adbf8d03af2bc7f9e2eeJakob Bornecrantz BUG_ON(*out_surf || *out_buf); 1207551a6697d08f92a311d6adbf8d03af2bc7f9e2eeJakob Bornecrantz 1208551a6697d08f92a311d6adbf8d03af2bc7f9e2eeJakob Bornecrantz ret = vmw_user_surface_lookup_handle(dev_priv, tfile, handle, out_surf); 1209551a6697d08f92a311d6adbf8d03af2bc7f9e2eeJakob Bornecrantz if (!ret) 1210551a6697d08f92a311d6adbf8d03af2bc7f9e2eeJakob Bornecrantz return 0; 1211551a6697d08f92a311d6adbf8d03af2bc7f9e2eeJakob Bornecrantz 1212551a6697d08f92a311d6adbf8d03af2bc7f9e2eeJakob Bornecrantz ret = vmw_user_dmabuf_lookup(tfile, handle, out_buf); 1213551a6697d08f92a311d6adbf8d03af2bc7f9e2eeJakob Bornecrantz return ret; 1214551a6697d08f92a311d6adbf8d03af2bc7f9e2eeJakob Bornecrantz} 1215551a6697d08f92a311d6adbf8d03af2bc7f9e2eeJakob Bornecrantz 12165bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom 12177a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstromint vmw_user_surface_lookup_handle(struct vmw_private *dev_priv, 12187a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom struct ttm_object_file *tfile, 12197a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom uint32_t handle, struct vmw_surface **out) 1220fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 1221fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_resource *res; 1222fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_surface *srf; 1223fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_user_surface *user_srf; 12247a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom struct ttm_base_object *base; 12257a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom int ret = -EINVAL; 1226fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 12277a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom base = ttm_base_object_lookup(tfile, handle); 12287a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom if (unlikely(base == NULL)) 1229fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return -EINVAL; 1230fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 12317a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom if (unlikely(base->object_type != VMW_RES_SURFACE)) 12327a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom goto out_bad_resource; 12337a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom 12347a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom user_srf = container_of(base, struct vmw_user_surface, base); 12357a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom srf = &user_srf->srf; 12367a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom res = &srf->res; 12377a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom 12387a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom read_lock(&dev_priv->resource_lock); 12397a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom 12407a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom if (!res->avail || res->res_free != &vmw_user_surface_free) { 12417a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom read_unlock(&dev_priv->resource_lock); 12427a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom goto out_bad_resource; 12437a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom } 1244fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 12457a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom kref_get(&res->kref); 12467a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom read_unlock(&dev_priv->resource_lock); 1247fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1248fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz *out = srf; 12497a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom ret = 0; 12507a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom 12517a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstromout_bad_resource: 12527a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom ttm_base_object_unref(&base); 12537a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom 12547a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom return ret; 1255fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 1256fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1257fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzstatic void vmw_user_surface_base_release(struct ttm_base_object **p_base) 1258fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 1259fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct ttm_base_object *base = *p_base; 1260fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_user_surface *user_srf = 1261fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz container_of(base, struct vmw_user_surface, base); 1262fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_resource *res = &user_srf->srf.res; 1263fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1264fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz *p_base = NULL; 1265fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz vmw_resource_unreference(&res); 1266fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 1267fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1268fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzint vmw_surface_destroy_ioctl(struct drm_device *dev, void *data, 1269fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct drm_file *file_priv) 1270fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 1271fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct drm_vmw_surface_arg *arg = (struct drm_vmw_surface_arg *)data; 1272fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile; 1273fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 12747a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom return ttm_ref_object_base_unref(tfile, arg->sid, TTM_REF_USAGE); 1275fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 1276fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1277fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzint vmw_surface_define_ioctl(struct drm_device *dev, void *data, 1278fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct drm_file *file_priv) 1279fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 1280fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_private *dev_priv = vmw_priv(dev); 12810c5d37033b3a16fdf6442730cee82dd3e8465fb1Dan Carpenter struct vmw_user_surface *user_srf; 1282fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_surface *srf; 1283fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_resource *res; 1284fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_resource *tmp; 1285fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz union drm_vmw_surface_create_arg *arg = 1286fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz (union drm_vmw_surface_create_arg *)data; 1287fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct drm_vmw_surface_create_req *req = &arg->req; 1288fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct drm_vmw_surface_arg *rep = &arg->rep; 1289fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile; 1290fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct drm_vmw_size __user *user_sizes; 1291fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz int ret; 12925bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom int i, j; 12935bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom uint32_t cur_bo_offset; 12945bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom struct drm_vmw_size *cur_size; 12955bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom struct vmw_surface_offset *cur_offset; 12965bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom uint32_t stride_bpp; 12975bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom uint32_t bpp; 1298414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom uint32_t num_sizes; 1299414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom uint32_t size; 1300414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom struct vmw_master *vmaster = vmw_master(file_priv->master); 1301fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1302414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom if (unlikely(vmw_user_surface_size == 0)) 1303414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom vmw_user_surface_size = ttm_round_pot(sizeof(*user_srf)) + 1304414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom 128; 1305414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom 1306414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom num_sizes = 0; 1307414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom for (i = 0; i < DRM_VMW_MAX_SURFACE_FACES; ++i) 1308414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom num_sizes += req->mip_levels[i]; 1309414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom 1310414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom if (num_sizes > DRM_VMW_MAX_SURFACE_FACES * 1311414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom DRM_VMW_MAX_MIP_LEVELS) 1312414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom return -EINVAL; 1313414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom 1314414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom size = vmw_user_surface_size + 128 + 1315414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom ttm_round_pot(num_sizes * sizeof(struct drm_vmw_size)) + 1316414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom ttm_round_pot(num_sizes * sizeof(struct vmw_surface_offset)); 1317414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom 1318414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom 1319414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom ret = ttm_read_lock(&vmaster->lock, true); 1320414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom if (unlikely(ret != 0)) 1321414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom return ret; 1322414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom 1323414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom ret = ttm_mem_global_alloc(vmw_mem_glob(dev_priv), 1324414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom size, false, true); 1325414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom if (unlikely(ret != 0)) { 1326414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom if (ret != -ERESTARTSYS) 1327414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom DRM_ERROR("Out of graphics memory for surface" 1328414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom " creation.\n"); 1329414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom goto out_unlock; 1330414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom } 1331414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom 1332414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom user_srf = kmalloc(sizeof(*user_srf), GFP_KERNEL); 1333414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom if (unlikely(user_srf == NULL)) { 1334414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom ret = -ENOMEM; 1335414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom goto out_no_user_srf; 1336414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom } 1337fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1338fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz srf = &user_srf->srf; 1339fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz res = &srf->res; 1340fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1341fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz srf->flags = req->flags; 1342fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz srf->format = req->format; 1343a87897edbae2d60db7bcb6bb0a75e82013d68305Jakob Bornecrantz srf->scanout = req->scanout; 13445bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom srf->backup = NULL; 13455bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom 1346fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz memcpy(srf->mip_levels, req->mip_levels, sizeof(srf->mip_levels)); 1347414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom srf->num_sizes = num_sizes; 1348414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom user_srf->size = size; 1349fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1350fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz srf->sizes = kmalloc(srf->num_sizes * sizeof(*srf->sizes), GFP_KERNEL); 1351fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (unlikely(srf->sizes == NULL)) { 1352fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ret = -ENOMEM; 1353414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom goto out_no_sizes; 1354fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz } 13555bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom srf->offsets = kmalloc(srf->num_sizes * sizeof(*srf->offsets), 13565bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom GFP_KERNEL); 13575bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom if (unlikely(srf->sizes == NULL)) { 13585bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom ret = -ENOMEM; 13595bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom goto out_no_offsets; 13605bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom } 1361fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1362fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz user_sizes = (struct drm_vmw_size __user *)(unsigned long) 1363fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz req->size_addr; 1364fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1365fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ret = copy_from_user(srf->sizes, user_sizes, 1366fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz srf->num_sizes * sizeof(*srf->sizes)); 13679b8eb4d14767209c83087063352cd04266ecdfd1Dan Carpenter if (unlikely(ret != 0)) { 13689b8eb4d14767209c83087063352cd04266ecdfd1Dan Carpenter ret = -EFAULT; 1369414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom goto out_no_copy; 13709b8eb4d14767209c83087063352cd04266ecdfd1Dan Carpenter } 1371fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 13725bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom cur_bo_offset = 0; 13735bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom cur_offset = srf->offsets; 13745bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom cur_size = srf->sizes; 13755bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom 13765bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom bpp = vmw_sf_bpp[srf->format].bpp; 13775bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom stride_bpp = vmw_sf_bpp[srf->format].s_bpp; 13785bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom 13795bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom for (i = 0; i < DRM_VMW_MAX_SURFACE_FACES; ++i) { 13805bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom for (j = 0; j < srf->mip_levels[i]; ++j) { 13815bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom uint32_t stride = 13825bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom (cur_size->width * stride_bpp + 7) >> 3; 13835bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom 13845bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom cur_offset->face = i; 13855bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom cur_offset->mip = j; 13865bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom cur_offset->bo_offset = cur_bo_offset; 13875bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom cur_bo_offset += stride * cur_size->height * 13885bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom cur_size->depth * bpp / stride_bpp; 13895bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom ++cur_offset; 13905bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom ++cur_size; 13915bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom } 13925bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom } 13935bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom srf->backup_size = cur_bo_offset; 13945bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom 13955ffdb658f605cbc420944e7c7eeec9fbb8a73772Jakob Bornecrantz if (srf->scanout && 139650ec3b7c35fda131e92abc6f9d93a230b7e009ebThomas Hellstrom srf->num_sizes == 1 && 139750ec3b7c35fda131e92abc6f9d93a230b7e009ebThomas Hellstrom srf->sizes[0].width == 64 && 139850ec3b7c35fda131e92abc6f9d93a230b7e009ebThomas Hellstrom srf->sizes[0].height == 64 && 139950ec3b7c35fda131e92abc6f9d93a230b7e009ebThomas Hellstrom srf->format == SVGA3D_A8R8G8B8) { 140050ec3b7c35fda131e92abc6f9d93a230b7e009ebThomas Hellstrom 1401f35119d6681300ba6d76da53cb1ebc2eed62e77aRakib Mullick /* allocate image area and clear it */ 1402f35119d6681300ba6d76da53cb1ebc2eed62e77aRakib Mullick srf->snooper.image = kzalloc(64 * 64 * 4, GFP_KERNEL); 1403f35119d6681300ba6d76da53cb1ebc2eed62e77aRakib Mullick if (!srf->snooper.image) { 140450ec3b7c35fda131e92abc6f9d93a230b7e009ebThomas Hellstrom DRM_ERROR("Failed to allocate cursor_image\n"); 140550ec3b7c35fda131e92abc6f9d93a230b7e009ebThomas Hellstrom ret = -ENOMEM; 1406414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom goto out_no_copy; 140750ec3b7c35fda131e92abc6f9d93a230b7e009ebThomas Hellstrom } 140850ec3b7c35fda131e92abc6f9d93a230b7e009ebThomas Hellstrom } else { 140950ec3b7c35fda131e92abc6f9d93a230b7e009ebThomas Hellstrom srf->snooper.image = NULL; 141050ec3b7c35fda131e92abc6f9d93a230b7e009ebThomas Hellstrom } 141150ec3b7c35fda131e92abc6f9d93a230b7e009ebThomas Hellstrom srf->snooper.crtc = NULL; 141250ec3b7c35fda131e92abc6f9d93a230b7e009ebThomas Hellstrom 1413fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz user_srf->base.shareable = false; 1414fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz user_srf->base.tfile = NULL; 1415fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1416fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz /** 1417fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * From this point, the generic resource management functions 1418fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * destroy the object on failure. 1419fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz */ 1420fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1421fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ret = vmw_surface_init(dev_priv, srf, vmw_user_surface_free); 1422fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (unlikely(ret != 0)) 1423414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom goto out_unlock; 1424fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1425fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz tmp = vmw_resource_reference(&srf->res); 1426fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ret = ttm_base_object_init(tfile, &user_srf->base, 1427fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz req->shareable, VMW_RES_SURFACE, 1428fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz &vmw_user_surface_base_release, NULL); 1429fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1430fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (unlikely(ret != 0)) { 1431fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz vmw_resource_unreference(&tmp); 1432fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz vmw_resource_unreference(&res); 1433414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom goto out_unlock; 1434fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz } 1435fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 14367a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom rep->sid = user_srf->base.hash.key; 14377a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom if (rep->sid == SVGA3D_INVALID_ID) 14387a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom DRM_ERROR("Created bad Surface ID.\n"); 14397a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom 1440fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz vmw_resource_unreference(&res); 1441414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom 1442414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom ttm_read_unlock(&vmaster->lock); 1443fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return 0; 1444414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstromout_no_copy: 14455bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom kfree(srf->offsets); 14465bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstromout_no_offsets: 1447fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz kfree(srf->sizes); 1448414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstromout_no_sizes: 1449fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz kfree(user_srf); 1450414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstromout_no_user_srf: 1451414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom ttm_mem_global_free(vmw_mem_glob(dev_priv), size); 1452414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstromout_unlock: 1453414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom ttm_read_unlock(&vmaster->lock); 1454fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return ret; 1455fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 1456fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1457fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzint vmw_surface_reference_ioctl(struct drm_device *dev, void *data, 1458fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct drm_file *file_priv) 1459fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 1460fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz union drm_vmw_surface_reference_arg *arg = 1461fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz (union drm_vmw_surface_reference_arg *)data; 1462fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct drm_vmw_surface_arg *req = &arg->req; 1463fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct drm_vmw_surface_create_req *rep = &arg->rep; 1464fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile; 1465fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_surface *srf; 1466fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_user_surface *user_srf; 1467fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct drm_vmw_size __user *user_sizes; 14687a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom struct ttm_base_object *base; 14697a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom int ret = -EINVAL; 1470fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 14717a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom base = ttm_base_object_lookup(tfile, req->sid); 14727a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom if (unlikely(base == NULL)) { 14737a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom DRM_ERROR("Could not find surface to reference.\n"); 1474fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return -EINVAL; 1475fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz } 1476fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 14777a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom if (unlikely(base->object_type != VMW_RES_SURFACE)) 14787a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom goto out_bad_resource; 14797a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom 14807a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom user_srf = container_of(base, struct vmw_user_surface, base); 14817a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom srf = &user_srf->srf; 1482fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1483fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ret = ttm_ref_object_add(tfile, &user_srf->base, TTM_REF_USAGE, NULL); 1484fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (unlikely(ret != 0)) { 1485fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz DRM_ERROR("Could not add a reference to a surface.\n"); 14867a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom goto out_no_reference; 1487fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz } 1488fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1489fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz rep->flags = srf->flags; 1490fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz rep->format = srf->format; 1491fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz memcpy(rep->mip_levels, srf->mip_levels, sizeof(srf->mip_levels)); 1492fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz user_sizes = (struct drm_vmw_size __user *)(unsigned long) 1493fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz rep->size_addr; 1494fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1495fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (user_sizes) 1496fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ret = copy_to_user(user_sizes, srf->sizes, 1497fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz srf->num_sizes * sizeof(*srf->sizes)); 14989b8eb4d14767209c83087063352cd04266ecdfd1Dan Carpenter if (unlikely(ret != 0)) { 1499fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz DRM_ERROR("copy_to_user failed %p %u\n", 1500fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz user_sizes, srf->num_sizes); 15019b8eb4d14767209c83087063352cd04266ecdfd1Dan Carpenter ret = -EFAULT; 15029b8eb4d14767209c83087063352cd04266ecdfd1Dan Carpenter } 15037a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstromout_bad_resource: 15047a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstromout_no_reference: 15057a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom ttm_base_object_unref(&base); 15067a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom 1507fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return ret; 1508fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 1509fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1510fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzint vmw_surface_check(struct vmw_private *dev_priv, 1511fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct ttm_object_file *tfile, 15127a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom uint32_t handle, int *id) 1513fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 15147a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom struct ttm_base_object *base; 15157a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom struct vmw_user_surface *user_srf; 1516fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 15177a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom int ret = -EPERM; 1518fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 15197a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom base = ttm_base_object_lookup(tfile, handle); 15207a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom if (unlikely(base == NULL)) 15217a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom return -EINVAL; 15227a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom 15237a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom if (unlikely(base->object_type != VMW_RES_SURFACE)) 15247a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom goto out_bad_surface; 15257a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom 15267a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom user_srf = container_of(base, struct vmw_user_surface, base); 15277a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom *id = user_srf->srf.res.id; 15287a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom ret = 0; 15297a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom 15307a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstromout_bad_surface: 15317a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom /** 15327a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom * FIXME: May deadlock here when called from the 15337a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom * command parsing code. 15347a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom */ 1535fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 15367a73ba7469cbea631050094fd14f73acebb97cf9Thomas Hellstrom ttm_base_object_unref(&base); 1537fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return ret; 1538fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 1539fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1540fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz/** 1541fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * Buffer management. 1542fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz */ 1543effe1105bef07f42366c20eac41b80ff9fcf675eThomas Hellstromvoid vmw_dmabuf_bo_free(struct ttm_buffer_object *bo) 1544effe1105bef07f42366c20eac41b80ff9fcf675eThomas Hellstrom{ 1545effe1105bef07f42366c20eac41b80ff9fcf675eThomas Hellstrom struct vmw_dma_buffer *vmw_bo = vmw_dma_buffer(bo); 1546effe1105bef07f42366c20eac41b80ff9fcf675eThomas Hellstrom 1547fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz kfree(vmw_bo); 1548fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 1549fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1550fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzint vmw_dmabuf_init(struct vmw_private *dev_priv, 1551fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_dma_buffer *vmw_bo, 1552fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz size_t size, struct ttm_placement *placement, 1553fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz bool interruptible, 1554fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz void (*bo_free) (struct ttm_buffer_object *bo)) 1555fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 1556fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct ttm_bo_device *bdev = &dev_priv->bdev; 1557fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz size_t acc_size; 1558fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz int ret; 1559fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1560fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz BUG_ON(!bo_free); 1561fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 156257de4ba959b290f0b8cf36ecd5e7f1b29d4b8a12Jerome Glisse acc_size = ttm_bo_acc_size(bdev, size, sizeof(struct vmw_dma_buffer)); 1563fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz memset(vmw_bo, 0, sizeof(*vmw_bo)); 1564fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1565fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz INIT_LIST_HEAD(&vmw_bo->validate_list); 1566fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1567fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ret = ttm_bo_init(bdev, &vmw_bo->base, size, 1568fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ttm_bo_type_device, placement, 1569fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 0, 0, interruptible, 1570fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz NULL, acc_size, bo_free); 1571fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return ret; 1572fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 1573fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1574fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzstatic void vmw_user_dmabuf_destroy(struct ttm_buffer_object *bo) 1575fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 1576fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_user_dma_buffer *vmw_user_bo = vmw_user_dma_buffer(bo); 1577fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1578fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz kfree(vmw_user_bo); 1579fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 1580fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1581fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzstatic void vmw_user_dmabuf_release(struct ttm_base_object **p_base) 1582fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 1583fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_user_dma_buffer *vmw_user_bo; 1584fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct ttm_base_object *base = *p_base; 1585fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct ttm_buffer_object *bo; 1586fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1587fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz *p_base = NULL; 1588fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1589fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (unlikely(base == NULL)) 1590fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return; 1591fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1592fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz vmw_user_bo = container_of(base, struct vmw_user_dma_buffer, base); 1593fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz bo = &vmw_user_bo->dma.base; 1594fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ttm_bo_unref(&bo); 1595fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 1596fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1597fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzint vmw_dmabuf_alloc_ioctl(struct drm_device *dev, void *data, 1598fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct drm_file *file_priv) 1599fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 1600fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_private *dev_priv = vmw_priv(dev); 1601fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz union drm_vmw_alloc_dmabuf_arg *arg = 1602fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz (union drm_vmw_alloc_dmabuf_arg *)data; 1603fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct drm_vmw_alloc_dmabuf_req *req = &arg->req; 1604fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct drm_vmw_dmabuf_rep *rep = &arg->rep; 1605fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_user_dma_buffer *vmw_user_bo; 1606fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct ttm_buffer_object *tmp; 1607fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_master *vmaster = vmw_master(file_priv->master); 1608fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz int ret; 1609fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1610fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz vmw_user_bo = kzalloc(sizeof(*vmw_user_bo), GFP_KERNEL); 1611fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (unlikely(vmw_user_bo == NULL)) 1612fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return -ENOMEM; 1613fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1614fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ret = ttm_read_lock(&vmaster->lock, true); 1615fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (unlikely(ret != 0)) { 1616fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz kfree(vmw_user_bo); 1617fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return ret; 1618fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz } 1619fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1620fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ret = vmw_dmabuf_init(dev_priv, &vmw_user_bo->dma, req->size, 16218ba5152a3acd5914cade42a1c8c9dc58ad8d1a89Thomas Hellstrom &vmw_vram_sys_placement, true, 1622fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz &vmw_user_dmabuf_destroy); 1623fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (unlikely(ret != 0)) 16242f5993cca67f9c80dcd390feef13695ca072b8a5Thomas Hellstrom goto out_no_dmabuf; 1625fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1626fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz tmp = ttm_bo_reference(&vmw_user_bo->dma.base); 1627fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ret = ttm_base_object_init(vmw_fpriv(file_priv)->tfile, 1628fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz &vmw_user_bo->base, 1629fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz false, 1630fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ttm_buffer_type, 1631fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz &vmw_user_dmabuf_release, NULL); 16322f5993cca67f9c80dcd390feef13695ca072b8a5Thomas Hellstrom if (unlikely(ret != 0)) 16332f5993cca67f9c80dcd390feef13695ca072b8a5Thomas Hellstrom goto out_no_base_object; 16342f5993cca67f9c80dcd390feef13695ca072b8a5Thomas Hellstrom else { 1635fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz rep->handle = vmw_user_bo->base.hash.key; 1636fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz rep->map_handle = vmw_user_bo->dma.base.addr_space_offset; 1637fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz rep->cur_gmr_id = vmw_user_bo->base.hash.key; 1638fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz rep->cur_gmr_offset = 0; 1639fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz } 1640fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 16412f5993cca67f9c80dcd390feef13695ca072b8a5Thomas Hellstromout_no_base_object: 16422f5993cca67f9c80dcd390feef13695ca072b8a5Thomas Hellstrom ttm_bo_unref(&tmp); 16432f5993cca67f9c80dcd390feef13695ca072b8a5Thomas Hellstromout_no_dmabuf: 1644fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ttm_read_unlock(&vmaster->lock); 1645fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 16462f5993cca67f9c80dcd390feef13695ca072b8a5Thomas Hellstrom return ret; 1647fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 1648fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1649fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzint vmw_dmabuf_unref_ioctl(struct drm_device *dev, void *data, 1650fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct drm_file *file_priv) 1651fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 1652fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct drm_vmw_unref_dmabuf_arg *arg = 1653fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz (struct drm_vmw_unref_dmabuf_arg *)data; 1654fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1655fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return ttm_ref_object_base_unref(vmw_fpriv(file_priv)->tfile, 1656fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz arg->handle, 1657fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz TTM_REF_USAGE); 1658fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 1659fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1660fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzuint32_t vmw_dmabuf_validate_node(struct ttm_buffer_object *bo, 1661fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz uint32_t cur_validate_node) 1662fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 1663fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_dma_buffer *vmw_bo = vmw_dma_buffer(bo); 1664fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1665fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (likely(vmw_bo->on_validate_list)) 1666fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return vmw_bo->cur_validate_node; 1667fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1668fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz vmw_bo->cur_validate_node = cur_validate_node; 1669fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz vmw_bo->on_validate_list = true; 1670fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1671fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return cur_validate_node; 1672fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 1673fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1674fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzvoid vmw_dmabuf_validate_clear(struct ttm_buffer_object *bo) 1675fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 1676fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_dma_buffer *vmw_bo = vmw_dma_buffer(bo); 1677fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1678fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz vmw_bo->on_validate_list = false; 1679fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 1680fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1681fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzint vmw_user_dmabuf_lookup(struct ttm_object_file *tfile, 1682fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz uint32_t handle, struct vmw_dma_buffer **out) 1683fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 1684fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_user_dma_buffer *vmw_user_bo; 1685fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct ttm_base_object *base; 1686fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1687fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz base = ttm_base_object_lookup(tfile, handle); 1688fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (unlikely(base == NULL)) { 1689fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz printk(KERN_ERR "Invalid buffer object handle 0x%08lx.\n", 1690fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz (unsigned long)handle); 1691fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return -ESRCH; 1692fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz } 1693fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1694fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (unlikely(base->object_type != ttm_buffer_type)) { 1695fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ttm_base_object_unref(&base); 1696fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz printk(KERN_ERR "Invalid buffer object handle 0x%08lx.\n", 1697fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz (unsigned long)handle); 1698fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return -EINVAL; 1699fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz } 1700fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1701fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz vmw_user_bo = container_of(base, struct vmw_user_dma_buffer, base); 1702fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz (void)ttm_bo_reference(&vmw_user_bo->dma.base); 1703fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ttm_base_object_unref(&base); 1704fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz *out = &vmw_user_bo->dma; 1705fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1706fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return 0; 1707fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 1708fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1709fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz/* 171065155b3708137fabee865dc4da822763c0c41208Uwe Kleine-König * Stream management 1711fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz */ 1712fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1713fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzstatic void vmw_stream_destroy(struct vmw_resource *res) 1714fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 1715fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_private *dev_priv = res->dev_priv; 1716fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_stream *stream; 1717fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz int ret; 1718fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1719fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz DRM_INFO("%s: unref\n", __func__); 1720fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz stream = container_of(res, struct vmw_stream, res); 1721fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1722fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ret = vmw_overlay_unref(dev_priv, stream->stream_id); 1723fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz WARN_ON(ret != 0); 1724fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 1725fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1726fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzstatic int vmw_stream_init(struct vmw_private *dev_priv, 1727fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_stream *stream, 1728fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz void (*res_free) (struct vmw_resource *res)) 1729fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 1730fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_resource *res = &stream->res; 1731fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz int ret; 1732fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1733fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ret = vmw_resource_init(dev_priv, res, &dev_priv->stream_idr, 17345bb39e818169783ee17ddbbefbd7bd16a4383fecThomas Hellstrom VMW_RES_STREAM, false, res_free, NULL); 1735fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1736fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (unlikely(ret != 0)) { 1737fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (res_free == NULL) 1738fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz kfree(stream); 1739fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz else 1740fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz res_free(&stream->res); 1741fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return ret; 1742fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz } 1743fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1744fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ret = vmw_overlay_claim(dev_priv, &stream->stream_id); 1745fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (ret) { 1746fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz vmw_resource_unreference(&res); 1747fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return ret; 1748fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz } 1749fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1750fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz DRM_INFO("%s: claimed\n", __func__); 1751fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1752fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz vmw_resource_activate(&stream->res, vmw_stream_destroy); 1753fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return 0; 1754fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 1755fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1756fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz/** 1757fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * User-space context management: 1758fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz */ 1759fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1760fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzstatic void vmw_user_stream_free(struct vmw_resource *res) 1761fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 1762fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_user_stream *stream = 1763fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz container_of(res, struct vmw_user_stream, stream.res); 1764414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom struct vmw_private *dev_priv = res->dev_priv; 1765fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1766fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz kfree(stream); 1767414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom ttm_mem_global_free(vmw_mem_glob(dev_priv), 1768414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom vmw_user_stream_size); 1769fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 1770fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1771fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz/** 1772fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * This function is called when user space has no more references on the 1773fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * base object. It releases the base-object's reference on the resource object. 1774fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz */ 1775fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1776fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzstatic void vmw_user_stream_base_release(struct ttm_base_object **p_base) 1777fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 1778fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct ttm_base_object *base = *p_base; 1779fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_user_stream *stream = 1780fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz container_of(base, struct vmw_user_stream, base); 1781fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_resource *res = &stream->stream.res; 1782fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1783fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz *p_base = NULL; 1784fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz vmw_resource_unreference(&res); 1785fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 1786fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1787fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzint vmw_stream_unref_ioctl(struct drm_device *dev, void *data, 1788fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct drm_file *file_priv) 1789fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 1790fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_private *dev_priv = vmw_priv(dev); 1791fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_resource *res; 1792fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_user_stream *stream; 1793fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct drm_vmw_stream_arg *arg = (struct drm_vmw_stream_arg *)data; 1794fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile; 1795fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz int ret = 0; 1796fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1797fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz res = vmw_resource_lookup(dev_priv, &dev_priv->stream_idr, arg->stream_id); 1798fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (unlikely(res == NULL)) 1799fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return -EINVAL; 1800fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1801fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (res->res_free != &vmw_user_stream_free) { 1802fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ret = -EINVAL; 1803fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz goto out; 1804fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz } 1805fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1806fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz stream = container_of(res, struct vmw_user_stream, stream.res); 1807fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (stream->base.tfile != tfile) { 1808fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ret = -EINVAL; 1809fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz goto out; 1810fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz } 1811fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1812fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ttm_ref_object_base_unref(tfile, stream->base.hash.key, TTM_REF_USAGE); 1813fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzout: 1814fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz vmw_resource_unreference(&res); 1815fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return ret; 1816fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 1817fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1818fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzint vmw_stream_claim_ioctl(struct drm_device *dev, void *data, 1819fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct drm_file *file_priv) 1820fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 1821fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_private *dev_priv = vmw_priv(dev); 1822414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom struct vmw_user_stream *stream; 1823fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_resource *res; 1824fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_resource *tmp; 1825fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct drm_vmw_stream_arg *arg = (struct drm_vmw_stream_arg *)data; 1826fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile; 1827414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom struct vmw_master *vmaster = vmw_master(file_priv->master); 1828fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz int ret; 1829fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1830414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom /* 1831414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom * Approximate idr memory usage with 128 bytes. It will be limited 1832414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom * by maximum number_of streams anyway? 1833414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom */ 1834414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom 1835414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom if (unlikely(vmw_user_stream_size == 0)) 1836414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom vmw_user_stream_size = ttm_round_pot(sizeof(*stream)) + 128; 1837414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom 1838414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom ret = ttm_read_lock(&vmaster->lock, true); 1839414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom if (unlikely(ret != 0)) 1840414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom return ret; 1841414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom 1842414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom ret = ttm_mem_global_alloc(vmw_mem_glob(dev_priv), 1843414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom vmw_user_stream_size, 1844414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom false, true); 1845414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom if (unlikely(ret != 0)) { 1846414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom if (ret != -ERESTARTSYS) 1847414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom DRM_ERROR("Out of graphics memory for stream" 1848414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom " creation.\n"); 1849414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom goto out_unlock; 1850414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom } 1851414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom 1852414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom 1853414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom stream = kmalloc(sizeof(*stream), GFP_KERNEL); 1854414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom if (unlikely(stream == NULL)) { 1855414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom ttm_mem_global_free(vmw_mem_glob(dev_priv), 1856414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom vmw_user_stream_size); 1857414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom ret = -ENOMEM; 1858414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom goto out_unlock; 1859414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom } 1860fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1861fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz res = &stream->stream.res; 1862fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz stream->base.shareable = false; 1863fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz stream->base.tfile = NULL; 1864fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1865414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom /* 1866414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom * From here on, the destructor takes over resource freeing. 1867414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom */ 1868414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom 1869fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ret = vmw_stream_init(dev_priv, &stream->stream, vmw_user_stream_free); 1870fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (unlikely(ret != 0)) 1871414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom goto out_unlock; 1872fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1873fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz tmp = vmw_resource_reference(res); 1874fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ret = ttm_base_object_init(tfile, &stream->base, false, VMW_RES_STREAM, 1875fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz &vmw_user_stream_base_release, NULL); 1876fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1877fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (unlikely(ret != 0)) { 1878fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz vmw_resource_unreference(&tmp); 1879fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz goto out_err; 1880fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz } 1881fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1882fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz arg->stream_id = res->id; 1883fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzout_err: 1884fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz vmw_resource_unreference(&res); 1885414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstromout_unlock: 1886414ee50b3a111983056b1a828fac08f9e8fbc7e9Thomas Hellstrom ttm_read_unlock(&vmaster->lock); 1887fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return ret; 1888fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 1889fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1890fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzint vmw_user_stream_lookup(struct vmw_private *dev_priv, 1891fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct ttm_object_file *tfile, 1892fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz uint32_t *inout_id, struct vmw_resource **out) 1893fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 1894fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_user_stream *stream; 1895fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct vmw_resource *res; 1896fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz int ret; 1897fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1898fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz res = vmw_resource_lookup(dev_priv, &dev_priv->stream_idr, *inout_id); 1899fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (unlikely(res == NULL)) 1900fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return -EINVAL; 1901fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1902fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (res->res_free != &vmw_user_stream_free) { 1903fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ret = -EINVAL; 1904fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz goto err_ref; 1905fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz } 1906fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1907fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz stream = container_of(res, struct vmw_user_stream, stream.res); 1908fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (stream->base.tfile != tfile) { 1909fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ret = -EPERM; 1910fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz goto err_ref; 1911fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz } 1912fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1913fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz *inout_id = stream->stream.stream_id; 1914fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz *out = res; 1915fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return 0; 1916fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzerr_ref: 1917fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz vmw_resource_unreference(&res); 1918fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return ret; 1919fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 1920