vmwgfx_dmabuf.c 7.7 KB

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