Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
vmwgfx_dmabuf.c
Go to the documentation of this file.
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 
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 
73 err:
74  ttm_write_unlock(&vmaster->lock);
75  return ret;
76 }
77 
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 
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 
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 
143 err_unreserve:
144  ttm_bo_unreserve(bo);
145 err:
146  ttm_write_unlock(&vmaster->lock);
147  return ret;
148 }
149 
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 
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);
236 err_unlock:
237  ttm_write_unlock(&vmaster->lock);
238 
239  return ret;
240 }
241 
242 
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,
268  interruptible);
269 }
270 
271 
280  SVGAGuestPtr *ptr)
281 {
282  if (bo->mem.mem_type == TTM_PL_VRAM) {
284  ptr->offset = bo->offset;
285  } else {
286  ptr->gmrId = bo->mem.start;
287  ptr->offset = 0;
288  }
289 }
290 
291 
300 void 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_GMR);
310 
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 }