Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v3.7-rc1 322 lines 9.1 kB view raw
1/************************************************************************** 2 * 3 * Copyright © 2011 VMware, Inc., Palo Alto, CA., USA 4 * All Rights Reserved. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the 8 * "Software"), to deal in the Software without restriction, including 9 * without limitation the rights to use, copy, modify, merge, publish, 10 * distribute, sub license, and/or sell copies of the Software, and to 11 * permit persons to whom the Software is furnished to do so, subject to 12 * the following conditions: 13 * 14 * The above copyright notice and this permission notice (including the 15 * next paragraph) shall be included in all copies or substantial portions 16 * of the Software. 17 * 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 21 * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, 22 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 23 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 24 * USE OR OTHER DEALINGS IN THE SOFTWARE. 25 * 26 **************************************************************************/ 27 28#include <drm/ttm/ttm_placement.h> 29 30#include <drm/drmP.h> 31#include "vmwgfx_drv.h" 32 33 34/** 35 * vmw_dmabuf_to_placement - Validate a buffer to placement. 36 * 37 * @dev_priv: Driver private. 38 * @buf: DMA buffer to move. 39 * @pin: Pin buffer if true. 40 * @interruptible: Use interruptible wait. 41 * 42 * May only be called by the current master since it assumes that the 43 * master lock is the current master's lock. 44 * This function takes the master's lock in write mode. 45 * Flushes and unpins the query bo to avoid failures. 46 * 47 * Returns 48 * -ERESTARTSYS if interrupted by a signal. 49 */ 50int vmw_dmabuf_to_placement(struct vmw_private *dev_priv, 51 struct vmw_dma_buffer *buf, 52 struct ttm_placement *placement, 53 bool interruptible) 54{ 55 struct vmw_master *vmaster = dev_priv->active_master; 56 struct ttm_buffer_object *bo = &buf->base; 57 int ret; 58 59 ret = ttm_write_lock(&vmaster->lock, interruptible); 60 if (unlikely(ret != 0)) 61 return ret; 62 63 vmw_execbuf_release_pinned_bo(dev_priv, false, 0); 64 65 ret = ttm_bo_reserve(bo, interruptible, false, false, 0); 66 if (unlikely(ret != 0)) 67 goto err; 68 69 ret = ttm_bo_validate(bo, placement, interruptible, false, false); 70 71 ttm_bo_unreserve(bo); 72 73err: 74 ttm_write_unlock(&vmaster->lock); 75 return ret; 76} 77 78/** 79 * vmw_dmabuf_to_vram_or_gmr - Move a buffer to vram or gmr. 80 * 81 * May only be called by the current master since it assumes that the 82 * master lock is the current master's lock. 83 * This function takes the master's lock in write mode. 84 * Flushes and unpins the query bo if @pin == true to avoid failures. 85 * 86 * @dev_priv: Driver private. 87 * @buf: DMA buffer to move. 88 * @pin: Pin buffer if true. 89 * @interruptible: Use interruptible wait. 90 * 91 * Returns 92 * -ERESTARTSYS if interrupted by a signal. 93 */ 94int vmw_dmabuf_to_vram_or_gmr(struct vmw_private *dev_priv, 95 struct vmw_dma_buffer *buf, 96 bool pin, bool interruptible) 97{ 98 struct vmw_master *vmaster = dev_priv->active_master; 99 struct ttm_buffer_object *bo = &buf->base; 100 struct ttm_placement *placement; 101 int ret; 102 103 ret = ttm_write_lock(&vmaster->lock, interruptible); 104 if (unlikely(ret != 0)) 105 return ret; 106 107 if (pin) 108 vmw_execbuf_release_pinned_bo(dev_priv, false, 0); 109 110 ret = ttm_bo_reserve(bo, interruptible, false, false, 0); 111 if (unlikely(ret != 0)) 112 goto err; 113 114 /** 115 * Put BO in VRAM if there is space, otherwise as a GMR. 116 * If there is no space in VRAM and GMR ids are all used up, 117 * start evicting GMRs to make room. If the DMA buffer can't be 118 * used as a GMR, this will return -ENOMEM. 119 */ 120 121 if (pin) 122 placement = &vmw_vram_gmr_ne_placement; 123 else 124 placement = &vmw_vram_gmr_placement; 125 126 ret = ttm_bo_validate(bo, placement, interruptible, false, false); 127 if (likely(ret == 0) || ret == -ERESTARTSYS) 128 goto err_unreserve; 129 130 131 /** 132 * If that failed, try VRAM again, this time evicting 133 * previous contents. 134 */ 135 136 if (pin) 137 placement = &vmw_vram_ne_placement; 138 else 139 placement = &vmw_vram_placement; 140 141 ret = ttm_bo_validate(bo, placement, interruptible, false, false); 142 143err_unreserve: 144 ttm_bo_unreserve(bo); 145err: 146 ttm_write_unlock(&vmaster->lock); 147 return ret; 148} 149 150/** 151 * vmw_dmabuf_to_vram - Move a buffer to vram. 152 * 153 * May only be called by the current master since it assumes that the 154 * master lock is the current master's lock. 155 * This function takes the master's lock in write mode. 156 * 157 * @dev_priv: Driver private. 158 * @buf: DMA buffer to move. 159 * @pin: Pin buffer in vram if true. 160 * @interruptible: Use interruptible wait. 161 * 162 * Returns 163 * -ERESTARTSYS if interrupted by a signal. 164 */ 165int vmw_dmabuf_to_vram(struct vmw_private *dev_priv, 166 struct vmw_dma_buffer *buf, 167 bool pin, bool interruptible) 168{ 169 struct ttm_placement *placement; 170 171 if (pin) 172 placement = &vmw_vram_ne_placement; 173 else 174 placement = &vmw_vram_placement; 175 176 return vmw_dmabuf_to_placement(dev_priv, buf, 177 placement, 178 interruptible); 179} 180 181/** 182 * vmw_dmabuf_to_start_of_vram - Move a buffer to start of vram. 183 * 184 * May only be called by the current master since it assumes that the 185 * master lock is the current master's lock. 186 * This function takes the master's lock in write mode. 187 * Flushes and unpins the query bo if @pin == true to avoid failures. 188 * 189 * @dev_priv: Driver private. 190 * @buf: DMA buffer to move. 191 * @pin: Pin buffer in vram if true. 192 * @interruptible: Use interruptible wait. 193 * 194 * Returns 195 * -ERESTARTSYS if interrupted by a signal. 196 */ 197int vmw_dmabuf_to_start_of_vram(struct vmw_private *dev_priv, 198 struct vmw_dma_buffer *buf, 199 bool pin, bool interruptible) 200{ 201 struct vmw_master *vmaster = dev_priv->active_master; 202 struct ttm_buffer_object *bo = &buf->base; 203 struct ttm_placement placement; 204 int ret = 0; 205 206 if (pin) 207 placement = vmw_vram_ne_placement; 208 else 209 placement = vmw_vram_placement; 210 placement.lpfn = bo->num_pages; 211 212 ret = ttm_write_lock(&vmaster->lock, interruptible); 213 if (unlikely(ret != 0)) 214 return ret; 215 216 if (pin) 217 vmw_execbuf_release_pinned_bo(dev_priv, false, 0); 218 219 ret = ttm_bo_reserve(bo, interruptible, false, false, 0); 220 if (unlikely(ret != 0)) 221 goto err_unlock; 222 223 /* Is this buffer already in vram but not at the start of it? */ 224 if (bo->mem.mem_type == TTM_PL_VRAM && 225 bo->mem.start < bo->num_pages && 226 bo->mem.start > 0) 227 (void) ttm_bo_validate(bo, &vmw_sys_placement, false, 228 false, false); 229 230 ret = ttm_bo_validate(bo, &placement, interruptible, false, false); 231 232 /* For some reason we didn't up at the start of vram */ 233 WARN_ON(ret == 0 && bo->offset != 0); 234 235 ttm_bo_unreserve(bo); 236err_unlock: 237 ttm_write_unlock(&vmaster->lock); 238 239 return ret; 240} 241 242 243/** 244 * vmw_dmabuf_upin - Unpin the buffer given buffer, does not move the buffer. 245 * 246 * May only be called by the current master since it assumes that the 247 * master lock is the current master's lock. 248 * This function takes the master's lock in write mode. 249 * 250 * @dev_priv: Driver private. 251 * @buf: DMA buffer to unpin. 252 * @interruptible: Use interruptible wait. 253 * 254 * Returns 255 * -ERESTARTSYS if interrupted by a signal. 256 */ 257int vmw_dmabuf_unpin(struct vmw_private *dev_priv, 258 struct vmw_dma_buffer *buf, 259 bool interruptible) 260{ 261 /* 262 * We could in theory early out if the buffer is 263 * unpinned but we need to lock and reserve the buffer 264 * anyways so we don't gain much by that. 265 */ 266 return vmw_dmabuf_to_placement(dev_priv, buf, 267 &vmw_evictable_placement, 268 interruptible); 269} 270 271 272/** 273 * vmw_bo_get_guest_ptr - Get the guest ptr representing the current placement 274 * of a buffer. 275 * 276 * @bo: Pointer to a struct ttm_buffer_object. Must be pinned or reserved. 277 * @ptr: SVGAGuestPtr returning the result. 278 */ 279void vmw_bo_get_guest_ptr(const struct ttm_buffer_object *bo, 280 SVGAGuestPtr *ptr) 281{ 282 if (bo->mem.mem_type == TTM_PL_VRAM) { 283 ptr->gmrId = SVGA_GMR_FRAMEBUFFER; 284 ptr->offset = bo->offset; 285 } else { 286 ptr->gmrId = bo->mem.start; 287 ptr->offset = 0; 288 } 289} 290 291 292/** 293 * vmw_bo_pin - Pin or unpin a buffer object without moving it. 294 * 295 * @bo: The buffer object. Must be reserved, and present either in VRAM 296 * or GMR memory. 297 * @pin: Whether to pin or unpin. 298 * 299 */ 300void vmw_bo_pin(struct ttm_buffer_object *bo, bool pin) 301{ 302 uint32_t pl_flags; 303 struct ttm_placement placement; 304 uint32_t old_mem_type = bo->mem.mem_type; 305 int ret; 306 307 BUG_ON(!atomic_read(&bo->reserved)); 308 BUG_ON(old_mem_type != TTM_PL_VRAM && 309 old_mem_type != VMW_PL_FLAG_GMR); 310 311 pl_flags = TTM_PL_FLAG_VRAM | VMW_PL_FLAG_GMR | TTM_PL_FLAG_CACHED; 312 if (pin) 313 pl_flags |= TTM_PL_FLAG_NO_EVICT; 314 315 memset(&placement, 0, sizeof(placement)); 316 placement.num_placement = 1; 317 placement.placement = &pl_flags; 318 319 ret = ttm_bo_validate(bo, &placement, false, true, true); 320 321 BUG_ON(ret != 0 || bo->mem.mem_type != old_mem_type); 322}