vmwgfx_dmabuf.c 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323
  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. #include "ttm/ttm_placement.h"
  28. #include "drmP.h"
  29. #include "vmwgfx_drv.h"
  30. /**
  31. * vmw_dmabuf_to_placement - Validate a buffer to placement.
  32. *
  33. * @dev_priv: Driver private.
  34. * @buf: DMA buffer to move.
  35. * @pin: Pin buffer if true.
  36. * @interruptible: Use interruptible wait.
  37. *
  38. * May only be called by the current master since it assumes that the
  39. * master lock is the current master's lock.
  40. * This function takes the master's lock in write mode.
  41. * Flushes and unpins the query bo to avoid failures.
  42. *
  43. * Returns
  44. * -ERESTARTSYS if interrupted by a signal.
  45. */
  46. int vmw_dmabuf_to_placement(struct vmw_private *dev_priv,
  47. struct vmw_dma_buffer *buf,
  48. struct ttm_placement *placement,
  49. bool interruptible)
  50. {
  51. struct vmw_master *vmaster = dev_priv->active_master;
  52. struct ttm_buffer_object *bo = &buf->base;
  53. int ret;
  54. ret = ttm_write_lock(&vmaster->lock, interruptible);
  55. if (unlikely(ret != 0))
  56. return ret;
  57. vmw_execbuf_release_pinned_bo(dev_priv, false, 0);
  58. ret = ttm_bo_reserve(bo, interruptible, false, false, 0);
  59. if (unlikely(ret != 0))
  60. goto err;
  61. ret = ttm_bo_validate(bo, placement, interruptible, false, false);
  62. ttm_bo_unreserve(bo);
  63. err:
  64. ttm_write_unlock(&vmaster->lock);
  65. return ret;
  66. }
  67. /**
  68. * vmw_dmabuf_to_vram_or_gmr - Move a buffer to vram or gmr.
  69. *
  70. * May only be called by the current master since it assumes that the
  71. * master lock is the current master's lock.
  72. * This function takes the master's lock in write mode.
  73. * Flushes and unpins the query bo if @pin == true to avoid failures.
  74. *
  75. * @dev_priv: Driver private.
  76. * @buf: DMA buffer to move.
  77. * @pin: Pin buffer if true.
  78. * @interruptible: Use interruptible wait.
  79. *
  80. * Returns
  81. * -ERESTARTSYS if interrupted by a signal.
  82. */
  83. int vmw_dmabuf_to_vram_or_gmr(struct vmw_private *dev_priv,
  84. struct vmw_dma_buffer *buf,
  85. bool pin, bool interruptible)
  86. {
  87. struct vmw_master *vmaster = dev_priv->active_master;
  88. struct ttm_buffer_object *bo = &buf->base;
  89. struct ttm_placement *placement;
  90. int ret;
  91. ret = ttm_write_lock(&vmaster->lock, interruptible);
  92. if (unlikely(ret != 0))
  93. return ret;
  94. if (pin)
  95. vmw_execbuf_release_pinned_bo(dev_priv, false, 0);
  96. ret = ttm_bo_reserve(bo, interruptible, false, false, 0);
  97. if (unlikely(ret != 0))
  98. goto err;
  99. /**
  100. * Put BO in VRAM if there is space, otherwise as a GMR.
  101. * If there is no space in VRAM and GMR ids are all used up,
  102. * start evicting GMRs to make room. If the DMA buffer can't be
  103. * used as a GMR, this will return -ENOMEM.
  104. */
  105. if (pin)
  106. placement = &vmw_vram_gmr_ne_placement;
  107. else
  108. placement = &vmw_vram_gmr_placement;
  109. ret = ttm_bo_validate(bo, placement, interruptible, false, false);
  110. if (likely(ret == 0) || ret == -ERESTARTSYS)
  111. goto err_unreserve;
  112. /**
  113. * If that failed, try VRAM again, this time evicting
  114. * previous contents.
  115. */
  116. if (pin)
  117. placement = &vmw_vram_ne_placement;
  118. else
  119. placement = &vmw_vram_placement;
  120. ret = ttm_bo_validate(bo, placement, interruptible, false, false);
  121. err_unreserve:
  122. ttm_bo_unreserve(bo);
  123. err:
  124. ttm_write_unlock(&vmaster->lock);
  125. return ret;
  126. }
  127. /**
  128. * vmw_dmabuf_to_vram - Move a buffer to vram.
  129. *
  130. * May only be called by the current master since it assumes that the
  131. * master lock is the current master's lock.
  132. * This function takes the master's lock in write mode.
  133. *
  134. * @dev_priv: Driver private.
  135. * @buf: DMA buffer to move.
  136. * @pin: Pin buffer in vram if true.
  137. * @interruptible: Use interruptible wait.
  138. *
  139. * Returns
  140. * -ERESTARTSYS if interrupted by a signal.
  141. */
  142. int vmw_dmabuf_to_vram(struct vmw_private *dev_priv,
  143. struct vmw_dma_buffer *buf,
  144. bool pin, bool interruptible)
  145. {
  146. struct ttm_placement *placement;
  147. if (pin)
  148. placement = &vmw_vram_ne_placement;
  149. else
  150. placement = &vmw_vram_placement;
  151. return vmw_dmabuf_to_placement(dev_priv, buf,
  152. placement,
  153. interruptible);
  154. }
  155. /**
  156. * vmw_dmabuf_to_start_of_vram - Move a buffer to start of vram.
  157. *
  158. * May only be called by the current master since it assumes that the
  159. * master lock is the current master's lock.
  160. * This function takes the master's lock in write mode.
  161. * Flushes and unpins the query bo if @pin == true to avoid failures.
  162. *
  163. * @dev_priv: Driver private.
  164. * @buf: DMA buffer to move.
  165. * @pin: Pin buffer in vram if true.
  166. * @interruptible: Use interruptible wait.
  167. *
  168. * Returns
  169. * -ERESTARTSYS if interrupted by a signal.
  170. */
  171. int vmw_dmabuf_to_start_of_vram(struct vmw_private *dev_priv,
  172. struct vmw_dma_buffer *buf,
  173. bool pin, bool interruptible)
  174. {
  175. struct vmw_master *vmaster = dev_priv->active_master;
  176. struct ttm_buffer_object *bo = &buf->base;
  177. struct ttm_placement placement;
  178. int ret = 0;
  179. if (pin)
  180. placement = vmw_vram_ne_placement;
  181. else
  182. placement = vmw_vram_placement;
  183. placement.lpfn = bo->num_pages;
  184. ret = ttm_write_lock(&vmaster->lock, interruptible);
  185. if (unlikely(ret != 0))
  186. return ret;
  187. if (pin)
  188. vmw_execbuf_release_pinned_bo(dev_priv, false, 0);
  189. ret = ttm_bo_reserve(bo, interruptible, false, false, 0);
  190. if (unlikely(ret != 0))
  191. goto err_unlock;
  192. /* Is this buffer already in vram but not at the start of it? */
  193. if (bo->mem.mem_type == TTM_PL_VRAM &&
  194. bo->mem.start < bo->num_pages &&
  195. bo->mem.start > 0)
  196. (void) ttm_bo_validate(bo, &vmw_sys_placement, false,
  197. false, false);
  198. ret = ttm_bo_validate(bo, &placement, interruptible, false, false);
  199. /* For some reason we didn't up at the start of vram */
  200. WARN_ON(ret == 0 && bo->offset != 0);
  201. ttm_bo_unreserve(bo);
  202. err_unlock:
  203. ttm_write_unlock(&vmaster->lock);
  204. return ret;
  205. }
  206. /**
  207. * vmw_dmabuf_upin - Unpin the buffer given buffer, does not move the buffer.
  208. *
  209. * May only be called by the current master since it assumes that the
  210. * master lock is the current master's lock.
  211. * This function takes the master's lock in write mode.
  212. *
  213. * @dev_priv: Driver private.
  214. * @buf: DMA buffer to unpin.
  215. * @interruptible: Use interruptible wait.
  216. *
  217. * Returns
  218. * -ERESTARTSYS if interrupted by a signal.
  219. */
  220. int vmw_dmabuf_unpin(struct vmw_private *dev_priv,
  221. struct vmw_dma_buffer *buf,
  222. bool interruptible)
  223. {
  224. /*
  225. * We could in theory early out if the buffer is
  226. * unpinned but we need to lock and reserve the buffer
  227. * anyways so we don't gain much by that.
  228. */
  229. return vmw_dmabuf_to_placement(dev_priv, buf,
  230. &vmw_evictable_placement,
  231. interruptible);
  232. }
  233. /**
  234. * vmw_bo_get_guest_ptr - Get the guest ptr representing the current placement
  235. * of a buffer.
  236. *
  237. * @bo: Pointer to a struct ttm_buffer_object. Must be pinned or reserved.
  238. * @ptr: SVGAGuestPtr returning the result.
  239. */
  240. void vmw_bo_get_guest_ptr(const struct ttm_buffer_object *bo,
  241. SVGAGuestPtr *ptr)
  242. {
  243. if (bo->mem.mem_type == TTM_PL_VRAM) {
  244. ptr->gmrId = SVGA_GMR_FRAMEBUFFER;
  245. ptr->offset = bo->offset;
  246. } else {
  247. ptr->gmrId = bo->mem.start;
  248. ptr->offset = 0;
  249. }
  250. }
  251. /**
  252. * vmw_bo_pin - Pin or unpin a buffer object without moving it.
  253. *
  254. * @bo: The buffer object. Must be reserved, and present either in VRAM
  255. * or GMR memory.
  256. * @pin: Whether to pin or unpin.
  257. *
  258. */
  259. void vmw_bo_pin(struct ttm_buffer_object *bo, bool pin)
  260. {
  261. uint32_t pl_flags;
  262. struct ttm_placement placement;
  263. uint32_t old_mem_type = bo->mem.mem_type;
  264. int ret;
  265. BUG_ON(!atomic_read(&bo->reserved));
  266. BUG_ON(old_mem_type != TTM_PL_VRAM &&
  267. old_mem_type != VMW_PL_GMR);
  268. pl_flags = TTM_PL_FLAG_VRAM | VMW_PL_FLAG_GMR | TTM_PL_FLAG_CACHED;
  269. if (pin)
  270. pl_flags |= TTM_PL_FLAG_NO_EVICT;
  271. memset(&placement, 0, sizeof(placement));
  272. placement.num_placement = 1;
  273. placement.placement = &pl_flags;
  274. ret = ttm_bo_validate(bo, &placement, false, true, true);
  275. BUG_ON(ret != 0 || bo->mem.mem_type != old_mem_type);
  276. }