vmwgfx_bo.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892
  1. // SPDX-License-Identifier: GPL-2.0 OR MIT
  2. /**************************************************************************
  3. *
  4. * Copyright (c) 2011-2024 Broadcom. All Rights Reserved. The term
  5. * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries.
  6. *
  7. * Permission is hereby granted, free of charge, to any person obtaining a
  8. * copy of this software and associated documentation files (the
  9. * "Software"), to deal in the Software without restriction, including
  10. * without limitation the rights to use, copy, modify, merge, publish,
  11. * distribute, sub license, and/or sell copies of the Software, and to
  12. * permit persons to whom the Software is furnished to do so, subject to
  13. * the following conditions:
  14. *
  15. * The above copyright notice and this permission notice (including the
  16. * next paragraph) shall be included in all copies or substantial portions
  17. * of the Software.
  18. *
  19. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  20. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  21. * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
  22. * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
  23. * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
  24. * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
  25. * USE OR OTHER DEALINGS IN THE SOFTWARE.
  26. *
  27. **************************************************************************/
  28. #include "vmwgfx_bo.h"
  29. #include "vmwgfx_drv.h"
  30. #include "vmwgfx_resource_priv.h"
  31. #include <drm/ttm/ttm_placement.h>
  32. static void vmw_bo_release(struct vmw_bo *vbo)
  33. {
  34. struct vmw_resource *res;
  35. WARN_ON(vbo->tbo.base.funcs &&
  36. kref_read(&vbo->tbo.base.refcount) != 0);
  37. vmw_bo_unmap(vbo);
  38. xa_destroy(&vbo->detached_resources);
  39. WARN_ON(vbo->is_dumb && !vbo->dumb_surface);
  40. if (vbo->is_dumb && vbo->dumb_surface) {
  41. res = &vbo->dumb_surface->res;
  42. WARN_ON(vbo != res->guest_memory_bo);
  43. WARN_ON(!res->guest_memory_bo);
  44. if (res->guest_memory_bo) {
  45. /* Reserve and switch the backing mob. */
  46. mutex_lock(&res->dev_priv->cmdbuf_mutex);
  47. (void)vmw_resource_reserve(res, false, true);
  48. vmw_resource_mob_detach(res);
  49. if (res->dirty)
  50. res->func->dirty_free(res);
  51. if (res->coherent)
  52. vmw_bo_dirty_release(res->guest_memory_bo);
  53. res->guest_memory_bo = NULL;
  54. res->guest_memory_offset = 0;
  55. vmw_resource_unreserve(res, true, false, false, NULL,
  56. 0);
  57. mutex_unlock(&res->dev_priv->cmdbuf_mutex);
  58. }
  59. vmw_surface_unreference(&vbo->dumb_surface);
  60. }
  61. drm_gem_object_release(&vbo->tbo.base);
  62. }
  63. /**
  64. * vmw_bo_free - vmw_bo destructor
  65. *
  66. * @bo: Pointer to the embedded struct ttm_buffer_object
  67. */
  68. static void vmw_bo_free(struct ttm_buffer_object *bo)
  69. {
  70. struct vmw_bo *vbo = to_vmw_bo(&bo->base);
  71. WARN_ON(!RB_EMPTY_ROOT(&vbo->res_tree));
  72. vmw_bo_release(vbo);
  73. WARN_ON(vbo->dirty);
  74. kfree(vbo);
  75. }
  76. /**
  77. * vmw_bo_pin_in_placement - Validate a buffer to placement.
  78. *
  79. * @dev_priv: Driver private.
  80. * @buf: DMA buffer to move.
  81. * @placement: The placement to pin it.
  82. * @interruptible: Use interruptible wait.
  83. * Return: Zero on success, Negative error code on failure. In particular
  84. * -ERESTARTSYS if interrupted by a signal
  85. */
  86. static int vmw_bo_pin_in_placement(struct vmw_private *dev_priv,
  87. struct vmw_bo *buf,
  88. struct ttm_placement *placement,
  89. bool interruptible)
  90. {
  91. struct ttm_operation_ctx ctx = {interruptible, false };
  92. struct ttm_buffer_object *bo = &buf->tbo;
  93. int ret;
  94. vmw_execbuf_release_pinned_bo(dev_priv);
  95. ret = ttm_bo_reserve(bo, interruptible, false, NULL);
  96. if (unlikely(ret != 0))
  97. goto err;
  98. ret = ttm_bo_validate(bo, placement, &ctx);
  99. if (!ret)
  100. vmw_bo_pin_reserved(buf, true);
  101. ttm_bo_unreserve(bo);
  102. err:
  103. return ret;
  104. }
  105. /**
  106. * vmw_bo_pin_in_vram_or_gmr - Move a buffer to vram or gmr.
  107. *
  108. * This function takes the reservation_sem in write mode.
  109. * Flushes and unpins the query bo to avoid failures.
  110. *
  111. * @dev_priv: Driver private.
  112. * @buf: DMA buffer to move.
  113. * @interruptible: Use interruptible wait.
  114. * Return: Zero on success, Negative error code on failure. In particular
  115. * -ERESTARTSYS if interrupted by a signal
  116. */
  117. int vmw_bo_pin_in_vram_or_gmr(struct vmw_private *dev_priv,
  118. struct vmw_bo *buf,
  119. bool interruptible)
  120. {
  121. struct ttm_operation_ctx ctx = {interruptible, false };
  122. struct ttm_buffer_object *bo = &buf->tbo;
  123. int ret;
  124. vmw_execbuf_release_pinned_bo(dev_priv);
  125. ret = ttm_bo_reserve(bo, interruptible, false, NULL);
  126. if (unlikely(ret != 0))
  127. goto err;
  128. vmw_bo_placement_set(buf,
  129. VMW_BO_DOMAIN_GMR | VMW_BO_DOMAIN_VRAM,
  130. VMW_BO_DOMAIN_GMR);
  131. ret = ttm_bo_validate(bo, &buf->placement, &ctx);
  132. if (likely(ret == 0) || ret == -ERESTARTSYS)
  133. goto out_unreserve;
  134. vmw_bo_placement_set(buf,
  135. VMW_BO_DOMAIN_VRAM,
  136. VMW_BO_DOMAIN_VRAM);
  137. ret = ttm_bo_validate(bo, &buf->placement, &ctx);
  138. out_unreserve:
  139. if (!ret)
  140. vmw_bo_pin_reserved(buf, true);
  141. ttm_bo_unreserve(bo);
  142. err:
  143. return ret;
  144. }
  145. /**
  146. * vmw_bo_pin_in_vram - Move a buffer to vram.
  147. *
  148. * This function takes the reservation_sem in write mode.
  149. * Flushes and unpins the query bo to avoid failures.
  150. *
  151. * @dev_priv: Driver private.
  152. * @buf: DMA buffer to move.
  153. * @interruptible: Use interruptible wait.
  154. * Return: Zero on success, Negative error code on failure. In particular
  155. * -ERESTARTSYS if interrupted by a signal
  156. */
  157. int vmw_bo_pin_in_vram(struct vmw_private *dev_priv,
  158. struct vmw_bo *buf,
  159. bool interruptible)
  160. {
  161. return vmw_bo_pin_in_placement(dev_priv, buf, &vmw_vram_placement,
  162. interruptible);
  163. }
  164. /**
  165. * vmw_bo_pin_in_start_of_vram - Move a buffer to start of vram.
  166. *
  167. * This function takes the reservation_sem in write mode.
  168. * Flushes and unpins the query bo to avoid failures.
  169. *
  170. * @dev_priv: Driver private.
  171. * @buf: DMA buffer to pin.
  172. * @interruptible: Use interruptible wait.
  173. * Return: Zero on success, Negative error code on failure. In particular
  174. * -ERESTARTSYS if interrupted by a signal
  175. */
  176. int vmw_bo_pin_in_start_of_vram(struct vmw_private *dev_priv,
  177. struct vmw_bo *buf,
  178. bool interruptible)
  179. {
  180. struct ttm_operation_ctx ctx = {interruptible, false };
  181. struct ttm_buffer_object *bo = &buf->tbo;
  182. int ret = 0;
  183. vmw_execbuf_release_pinned_bo(dev_priv);
  184. ret = ttm_bo_reserve(bo, interruptible, false, NULL);
  185. if (unlikely(ret != 0))
  186. goto err_unlock;
  187. /*
  188. * Is this buffer already in vram but not at the start of it?
  189. * In that case, evict it first because TTM isn't good at handling
  190. * that situation.
  191. */
  192. if (bo->resource->mem_type == TTM_PL_VRAM &&
  193. bo->resource->start < PFN_UP(bo->resource->size) &&
  194. bo->resource->start > 0 &&
  195. buf->tbo.pin_count == 0) {
  196. ctx.interruptible = false;
  197. vmw_bo_placement_set(buf,
  198. VMW_BO_DOMAIN_SYS,
  199. VMW_BO_DOMAIN_SYS);
  200. (void)ttm_bo_validate(bo, &buf->placement, &ctx);
  201. }
  202. vmw_bo_placement_set(buf,
  203. VMW_BO_DOMAIN_VRAM,
  204. VMW_BO_DOMAIN_VRAM);
  205. buf->places[0].lpfn = PFN_UP(bo->resource->size);
  206. buf->busy_places[0].lpfn = PFN_UP(bo->resource->size);
  207. ret = ttm_bo_validate(bo, &buf->placement, &ctx);
  208. /* For some reason we didn't end up at the start of vram */
  209. WARN_ON(ret == 0 && bo->resource->start != 0);
  210. if (!ret)
  211. vmw_bo_pin_reserved(buf, true);
  212. ttm_bo_unreserve(bo);
  213. err_unlock:
  214. return ret;
  215. }
  216. /**
  217. * vmw_bo_unpin - Unpin the buffer given buffer, does not move the buffer.
  218. *
  219. * This function takes the reservation_sem in write mode.
  220. *
  221. * @dev_priv: Driver private.
  222. * @buf: DMA buffer to unpin.
  223. * @interruptible: Use interruptible wait.
  224. * Return: Zero on success, Negative error code on failure. In particular
  225. * -ERESTARTSYS if interrupted by a signal
  226. */
  227. int vmw_bo_unpin(struct vmw_private *dev_priv,
  228. struct vmw_bo *buf,
  229. bool interruptible)
  230. {
  231. struct ttm_buffer_object *bo = &buf->tbo;
  232. int ret;
  233. ret = ttm_bo_reserve(bo, interruptible, false, NULL);
  234. if (unlikely(ret != 0))
  235. goto err;
  236. vmw_bo_pin_reserved(buf, false);
  237. ttm_bo_unreserve(bo);
  238. err:
  239. return ret;
  240. }
  241. /**
  242. * vmw_bo_get_guest_ptr - Get the guest ptr representing the current placement
  243. * of a buffer.
  244. *
  245. * @bo: Pointer to a struct ttm_buffer_object. Must be pinned or reserved.
  246. * @ptr: SVGAGuestPtr returning the result.
  247. */
  248. void vmw_bo_get_guest_ptr(const struct ttm_buffer_object *bo,
  249. SVGAGuestPtr *ptr)
  250. {
  251. if (bo->resource->mem_type == TTM_PL_VRAM) {
  252. ptr->gmrId = SVGA_GMR_FRAMEBUFFER;
  253. ptr->offset = bo->resource->start << PAGE_SHIFT;
  254. } else {
  255. ptr->gmrId = bo->resource->start;
  256. ptr->offset = 0;
  257. }
  258. }
  259. /**
  260. * vmw_bo_pin_reserved - Pin or unpin a buffer object without moving it.
  261. *
  262. * @vbo: The buffer object. Must be reserved.
  263. * @pin: Whether to pin or unpin.
  264. *
  265. */
  266. void vmw_bo_pin_reserved(struct vmw_bo *vbo, bool pin)
  267. {
  268. struct ttm_operation_ctx ctx = { false, true };
  269. struct ttm_place pl;
  270. struct ttm_placement placement;
  271. struct ttm_buffer_object *bo = &vbo->tbo;
  272. uint32_t old_mem_type = bo->resource->mem_type;
  273. int ret;
  274. dma_resv_assert_held(bo->base.resv);
  275. if (pin == !!bo->pin_count)
  276. return;
  277. pl.fpfn = 0;
  278. pl.lpfn = 0;
  279. pl.mem_type = bo->resource->mem_type;
  280. pl.flags = bo->resource->placement;
  281. memset(&placement, 0, sizeof(placement));
  282. placement.num_placement = 1;
  283. placement.placement = &pl;
  284. ret = ttm_bo_validate(bo, &placement, &ctx);
  285. BUG_ON(ret != 0 || bo->resource->mem_type != old_mem_type);
  286. if (pin)
  287. ttm_bo_pin(bo);
  288. else
  289. ttm_bo_unpin(bo);
  290. }
  291. /**
  292. * vmw_bo_map_and_cache - Map a buffer object and cache the map
  293. *
  294. * @vbo: The buffer object to map
  295. * Return: A kernel virtual address or NULL if mapping failed.
  296. *
  297. * This function maps a buffer object into the kernel address space, or
  298. * returns the virtual kernel address of an already existing map. The virtual
  299. * address remains valid as long as the buffer object is pinned or reserved.
  300. * The cached map is torn down on either
  301. * 1) Buffer object move
  302. * 2) Buffer object swapout
  303. * 3) Buffer object destruction
  304. *
  305. */
  306. void *vmw_bo_map_and_cache(struct vmw_bo *vbo)
  307. {
  308. return vmw_bo_map_and_cache_size(vbo, vbo->tbo.base.size);
  309. }
  310. void *vmw_bo_map_and_cache_size(struct vmw_bo *vbo, size_t size)
  311. {
  312. struct ttm_buffer_object *bo = &vbo->tbo;
  313. bool not_used;
  314. void *virtual;
  315. int ret;
  316. atomic_inc(&vbo->map_count);
  317. virtual = ttm_kmap_obj_virtual(&vbo->map, &not_used);
  318. if (virtual)
  319. return virtual;
  320. ret = ttm_bo_kmap(bo, 0, PFN_UP(size), &vbo->map);
  321. if (ret)
  322. DRM_ERROR("Buffer object map failed: %d (size: bo = %zu, map = %zu).\n",
  323. ret, bo->base.size, size);
  324. return ttm_kmap_obj_virtual(&vbo->map, &not_used);
  325. }
  326. /**
  327. * vmw_bo_unmap - Tear down a cached buffer object map.
  328. *
  329. * @vbo: The buffer object whose map we are tearing down.
  330. *
  331. * This function tears down a cached map set up using
  332. * vmw_bo_map_and_cache().
  333. */
  334. void vmw_bo_unmap(struct vmw_bo *vbo)
  335. {
  336. int map_count;
  337. if (vbo->map.bo == NULL)
  338. return;
  339. map_count = atomic_dec_return(&vbo->map_count);
  340. if (!map_count) {
  341. ttm_bo_kunmap(&vbo->map);
  342. vbo->map.bo = NULL;
  343. }
  344. }
  345. /**
  346. * vmw_bo_init - Initialize a vmw buffer object
  347. *
  348. * @dev_priv: Pointer to the device private struct
  349. * @vmw_bo: Buffer object to initialize
  350. * @params: Parameters used to initialize the buffer object
  351. * @destroy: The function used to delete the buffer object
  352. * Returns: Zero on success, negative error code on error.
  353. *
  354. */
  355. static int vmw_bo_init(struct vmw_private *dev_priv,
  356. struct vmw_bo *vmw_bo,
  357. struct vmw_bo_params *params,
  358. void (*destroy)(struct ttm_buffer_object *))
  359. {
  360. struct ttm_operation_ctx ctx = {
  361. .interruptible = params->bo_type != ttm_bo_type_kernel,
  362. .no_wait_gpu = false,
  363. .resv = params->resv,
  364. };
  365. struct ttm_device *bdev = &dev_priv->bdev;
  366. struct drm_device *vdev = &dev_priv->drm;
  367. int ret;
  368. memset(vmw_bo, 0, sizeof(*vmw_bo));
  369. BUILD_BUG_ON(TTM_MAX_BO_PRIORITY <= 3);
  370. vmw_bo->tbo.priority = 3;
  371. vmw_bo->res_tree = RB_ROOT;
  372. xa_init(&vmw_bo->detached_resources);
  373. atomic_set(&vmw_bo->map_count, 0);
  374. params->size = ALIGN(params->size, PAGE_SIZE);
  375. drm_gem_private_object_init(vdev, &vmw_bo->tbo.base, params->size);
  376. vmw_bo_placement_set(vmw_bo, params->domain, params->busy_domain);
  377. ret = ttm_bo_init_reserved(bdev, &vmw_bo->tbo, params->bo_type,
  378. &vmw_bo->placement, 0, &ctx,
  379. params->sg, params->resv, destroy);
  380. if (unlikely(ret))
  381. return ret;
  382. if (params->pin)
  383. ttm_bo_pin(&vmw_bo->tbo);
  384. if (!params->keep_resv)
  385. ttm_bo_unreserve(&vmw_bo->tbo);
  386. return 0;
  387. }
  388. int vmw_bo_create(struct vmw_private *vmw,
  389. struct vmw_bo_params *params,
  390. struct vmw_bo **p_bo)
  391. {
  392. int ret;
  393. *p_bo = kmalloc(sizeof(**p_bo), GFP_KERNEL);
  394. if (unlikely(!*p_bo)) {
  395. DRM_ERROR("Failed to allocate a buffer.\n");
  396. return -ENOMEM;
  397. }
  398. /*
  399. * vmw_bo_init will delete the *p_bo object if it fails
  400. */
  401. ret = vmw_bo_init(vmw, *p_bo, params, vmw_bo_free);
  402. if (unlikely(ret != 0))
  403. goto out_error;
  404. return ret;
  405. out_error:
  406. *p_bo = NULL;
  407. return ret;
  408. }
  409. /**
  410. * vmw_user_bo_synccpu_grab - Grab a struct vmw_bo for cpu
  411. * access, idling previous GPU operations on the buffer and optionally
  412. * blocking it for further command submissions.
  413. *
  414. * @vmw_bo: Pointer to the buffer object being grabbed for CPU access
  415. * @flags: Flags indicating how the grab should be performed.
  416. * Return: Zero on success, Negative error code on error. In particular,
  417. * -EBUSY will be returned if a dontblock operation is requested and the
  418. * buffer object is busy, and -ERESTARTSYS will be returned if a wait is
  419. * interrupted by a signal.
  420. *
  421. * A blocking grab will be automatically released when @tfile is closed.
  422. */
  423. static int vmw_user_bo_synccpu_grab(struct vmw_bo *vmw_bo,
  424. uint32_t flags)
  425. {
  426. bool nonblock = !!(flags & drm_vmw_synccpu_dontblock);
  427. struct ttm_buffer_object *bo = &vmw_bo->tbo;
  428. int ret;
  429. if (flags & drm_vmw_synccpu_allow_cs) {
  430. long lret;
  431. lret = dma_resv_wait_timeout(bo->base.resv, DMA_RESV_USAGE_READ,
  432. true, nonblock ? 0 :
  433. MAX_SCHEDULE_TIMEOUT);
  434. if (!lret)
  435. return -EBUSY;
  436. else if (lret < 0)
  437. return lret;
  438. return 0;
  439. }
  440. ret = ttm_bo_reserve(bo, true, nonblock, NULL);
  441. if (unlikely(ret != 0))
  442. return ret;
  443. ret = ttm_bo_wait(bo, true, nonblock);
  444. if (likely(ret == 0))
  445. atomic_inc(&vmw_bo->cpu_writers);
  446. ttm_bo_unreserve(bo);
  447. if (unlikely(ret != 0))
  448. return ret;
  449. return ret;
  450. }
  451. /**
  452. * vmw_user_bo_synccpu_release - Release a previous grab for CPU access,
  453. * and unblock command submission on the buffer if blocked.
  454. *
  455. * @filp: Identifying the caller.
  456. * @handle: Handle identifying the buffer object.
  457. * @flags: Flags indicating the type of release.
  458. */
  459. static int vmw_user_bo_synccpu_release(struct drm_file *filp,
  460. uint32_t handle,
  461. uint32_t flags)
  462. {
  463. struct vmw_bo *vmw_bo;
  464. int ret = vmw_user_bo_lookup(filp, handle, &vmw_bo);
  465. if (!ret) {
  466. if (!(flags & drm_vmw_synccpu_allow_cs)) {
  467. atomic_dec(&vmw_bo->cpu_writers);
  468. }
  469. vmw_user_bo_unref(&vmw_bo);
  470. }
  471. return ret;
  472. }
  473. /**
  474. * vmw_user_bo_synccpu_ioctl - ioctl function implementing the synccpu
  475. * functionality.
  476. *
  477. * @dev: Identifies the drm device.
  478. * @data: Pointer to the ioctl argument.
  479. * @file_priv: Identifies the caller.
  480. * Return: Zero on success, negative error code on error.
  481. *
  482. * This function checks the ioctl arguments for validity and calls the
  483. * relevant synccpu functions.
  484. */
  485. int vmw_user_bo_synccpu_ioctl(struct drm_device *dev, void *data,
  486. struct drm_file *file_priv)
  487. {
  488. struct drm_vmw_synccpu_arg *arg =
  489. (struct drm_vmw_synccpu_arg *) data;
  490. struct vmw_bo *vbo;
  491. int ret;
  492. if ((arg->flags & (drm_vmw_synccpu_read | drm_vmw_synccpu_write)) == 0
  493. || (arg->flags & ~(drm_vmw_synccpu_read | drm_vmw_synccpu_write |
  494. drm_vmw_synccpu_dontblock |
  495. drm_vmw_synccpu_allow_cs)) != 0) {
  496. DRM_ERROR("Illegal synccpu flags.\n");
  497. return -EINVAL;
  498. }
  499. switch (arg->op) {
  500. case drm_vmw_synccpu_grab:
  501. ret = vmw_user_bo_lookup(file_priv, arg->handle, &vbo);
  502. if (unlikely(ret != 0))
  503. return ret;
  504. ret = vmw_user_bo_synccpu_grab(vbo, arg->flags);
  505. vmw_user_bo_unref(&vbo);
  506. if (unlikely(ret != 0)) {
  507. if (ret == -ERESTARTSYS || ret == -EBUSY)
  508. return -EBUSY;
  509. DRM_ERROR("Failed synccpu grab on handle 0x%08x.\n",
  510. (unsigned int) arg->handle);
  511. return ret;
  512. }
  513. break;
  514. case drm_vmw_synccpu_release:
  515. ret = vmw_user_bo_synccpu_release(file_priv,
  516. arg->handle,
  517. arg->flags);
  518. if (unlikely(ret != 0)) {
  519. DRM_ERROR("Failed synccpu release on handle 0x%08x.\n",
  520. (unsigned int) arg->handle);
  521. return ret;
  522. }
  523. break;
  524. default:
  525. DRM_ERROR("Invalid synccpu operation.\n");
  526. return -EINVAL;
  527. }
  528. return 0;
  529. }
  530. /**
  531. * vmw_bo_unref_ioctl - Generic handle close ioctl.
  532. *
  533. * @dev: Identifies the drm device.
  534. * @data: Pointer to the ioctl argument.
  535. * @file_priv: Identifies the caller.
  536. * Return: Zero on success, negative error code on error.
  537. *
  538. * This function checks the ioctl arguments for validity and closes a
  539. * handle to a TTM base object, optionally freeing the object.
  540. */
  541. int vmw_bo_unref_ioctl(struct drm_device *dev, void *data,
  542. struct drm_file *file_priv)
  543. {
  544. struct drm_vmw_unref_dmabuf_arg *arg =
  545. (struct drm_vmw_unref_dmabuf_arg *)data;
  546. return drm_gem_handle_delete(file_priv, arg->handle);
  547. }
  548. /**
  549. * vmw_user_bo_lookup - Look up a vmw user buffer object from a handle.
  550. *
  551. * @filp: The file the handle is registered with.
  552. * @handle: The user buffer object handle
  553. * @out: Pointer to a where a pointer to the embedded
  554. * struct vmw_bo should be placed.
  555. * Return: Zero on success, Negative error code on error.
  556. *
  557. * The vmw buffer object pointer will be refcounted (both ttm and gem)
  558. */
  559. int vmw_user_bo_lookup(struct drm_file *filp,
  560. u32 handle,
  561. struct vmw_bo **out)
  562. {
  563. struct drm_gem_object *gobj;
  564. gobj = drm_gem_object_lookup(filp, handle);
  565. if (!gobj) {
  566. DRM_ERROR("Invalid buffer object handle 0x%08lx.\n",
  567. (unsigned long)handle);
  568. return -ESRCH;
  569. }
  570. *out = to_vmw_bo(gobj);
  571. return 0;
  572. }
  573. /**
  574. * vmw_bo_fence_single - Utility function to fence a single TTM buffer
  575. * object without unreserving it.
  576. *
  577. * @bo: Pointer to the struct ttm_buffer_object to fence.
  578. * @fence: Pointer to the fence. If NULL, this function will
  579. * insert a fence into the command stream..
  580. *
  581. * Contrary to the ttm_eu version of this function, it takes only
  582. * a single buffer object instead of a list, and it also doesn't
  583. * unreserve the buffer object, which needs to be done separately.
  584. */
  585. void vmw_bo_fence_single(struct ttm_buffer_object *bo,
  586. struct vmw_fence_obj *fence)
  587. {
  588. struct ttm_device *bdev = bo->bdev;
  589. struct vmw_private *dev_priv = vmw_priv_from_ttm(bdev);
  590. int ret;
  591. if (fence == NULL)
  592. vmw_execbuf_fence_commands(NULL, dev_priv, &fence, NULL);
  593. else
  594. dma_fence_get(&fence->base);
  595. ret = dma_resv_reserve_fences(bo->base.resv, 1);
  596. if (!ret)
  597. dma_resv_add_fence(bo->base.resv, &fence->base,
  598. DMA_RESV_USAGE_KERNEL);
  599. else
  600. /* Last resort fallback when we are OOM */
  601. dma_fence_wait(&fence->base, false);
  602. dma_fence_put(&fence->base);
  603. }
  604. /**
  605. * vmw_bo_swap_notify - swapout notify callback.
  606. *
  607. * @bo: The buffer object to be swapped out.
  608. */
  609. void vmw_bo_swap_notify(struct ttm_buffer_object *bo)
  610. {
  611. /* Kill any cached kernel maps before swapout */
  612. vmw_bo_unmap(to_vmw_bo(&bo->base));
  613. }
  614. /**
  615. * vmw_bo_move_notify - TTM move_notify_callback
  616. *
  617. * @bo: The TTM buffer object about to move.
  618. * @mem: The struct ttm_resource indicating to what memory
  619. * region the move is taking place.
  620. *
  621. * Detaches cached maps and device bindings that require that the
  622. * buffer doesn't move.
  623. */
  624. void vmw_bo_move_notify(struct ttm_buffer_object *bo,
  625. struct ttm_resource *mem)
  626. {
  627. struct vmw_bo *vbo = to_vmw_bo(&bo->base);
  628. /*
  629. * Kill any cached kernel maps before move to or from VRAM.
  630. * With other types of moves, the underlying pages stay the same,
  631. * and the map can be kept.
  632. */
  633. if (mem->mem_type == TTM_PL_VRAM || bo->resource->mem_type == TTM_PL_VRAM)
  634. vmw_bo_unmap(vbo);
  635. /*
  636. * If we're moving a backup MOB out of MOB placement, then make sure we
  637. * read back all resource content first, and unbind the MOB from
  638. * the resource.
  639. */
  640. if (mem->mem_type != VMW_PL_MOB && bo->resource->mem_type == VMW_PL_MOB)
  641. vmw_resource_unbind_list(vbo);
  642. }
  643. static u32 placement_flags(u32 domain, u32 desired, u32 fallback)
  644. {
  645. if (desired & fallback & domain)
  646. return 0;
  647. if (desired & domain)
  648. return TTM_PL_FLAG_DESIRED;
  649. return TTM_PL_FLAG_FALLBACK;
  650. }
  651. static u32
  652. set_placement_list(struct ttm_place *pl, u32 desired, u32 fallback)
  653. {
  654. u32 domain = desired | fallback;
  655. u32 n = 0;
  656. /*
  657. * The placements are ordered according to our preferences
  658. */
  659. if (domain & VMW_BO_DOMAIN_MOB) {
  660. pl[n].mem_type = VMW_PL_MOB;
  661. pl[n].flags = placement_flags(VMW_BO_DOMAIN_MOB, desired,
  662. fallback);
  663. pl[n].fpfn = 0;
  664. pl[n].lpfn = 0;
  665. n++;
  666. }
  667. if (domain & VMW_BO_DOMAIN_GMR) {
  668. pl[n].mem_type = VMW_PL_GMR;
  669. pl[n].flags = placement_flags(VMW_BO_DOMAIN_GMR, desired,
  670. fallback);
  671. pl[n].fpfn = 0;
  672. pl[n].lpfn = 0;
  673. n++;
  674. }
  675. if (domain & VMW_BO_DOMAIN_VRAM) {
  676. pl[n].mem_type = TTM_PL_VRAM;
  677. pl[n].flags = placement_flags(VMW_BO_DOMAIN_VRAM, desired,
  678. fallback);
  679. pl[n].fpfn = 0;
  680. pl[n].lpfn = 0;
  681. n++;
  682. }
  683. if (domain & VMW_BO_DOMAIN_WAITABLE_SYS) {
  684. pl[n].mem_type = VMW_PL_SYSTEM;
  685. pl[n].flags = placement_flags(VMW_BO_DOMAIN_WAITABLE_SYS,
  686. desired, fallback);
  687. pl[n].fpfn = 0;
  688. pl[n].lpfn = 0;
  689. n++;
  690. }
  691. if (domain & VMW_BO_DOMAIN_SYS) {
  692. pl[n].mem_type = TTM_PL_SYSTEM;
  693. pl[n].flags = placement_flags(VMW_BO_DOMAIN_SYS, desired,
  694. fallback);
  695. pl[n].fpfn = 0;
  696. pl[n].lpfn = 0;
  697. n++;
  698. }
  699. WARN_ON(!n);
  700. if (!n) {
  701. pl[n].mem_type = TTM_PL_SYSTEM;
  702. pl[n].flags = 0;
  703. pl[n].fpfn = 0;
  704. pl[n].lpfn = 0;
  705. n++;
  706. }
  707. return n;
  708. }
  709. void vmw_bo_placement_set(struct vmw_bo *bo, u32 domain, u32 busy_domain)
  710. {
  711. struct ttm_device *bdev = bo->tbo.bdev;
  712. struct vmw_private *vmw = vmw_priv_from_ttm(bdev);
  713. struct ttm_placement *pl = &bo->placement;
  714. bool mem_compatible = false;
  715. u32 i;
  716. pl->placement = bo->places;
  717. pl->num_placement = set_placement_list(bo->places, domain, busy_domain);
  718. if (drm_debug_enabled(DRM_UT_DRIVER) && bo->tbo.resource) {
  719. for (i = 0; i < pl->num_placement; ++i) {
  720. if (bo->tbo.resource->mem_type == TTM_PL_SYSTEM ||
  721. bo->tbo.resource->mem_type == pl->placement[i].mem_type)
  722. mem_compatible = true;
  723. }
  724. if (!mem_compatible)
  725. drm_warn(&vmw->drm,
  726. "%s: Incompatible transition from "
  727. "bo->base.resource->mem_type = %u to domain = %u\n",
  728. __func__, bo->tbo.resource->mem_type, domain);
  729. }
  730. }
  731. void vmw_bo_placement_set_default_accelerated(struct vmw_bo *bo)
  732. {
  733. struct ttm_device *bdev = bo->tbo.bdev;
  734. struct vmw_private *vmw = vmw_priv_from_ttm(bdev);
  735. u32 domain = VMW_BO_DOMAIN_GMR | VMW_BO_DOMAIN_VRAM;
  736. if (vmw->has_mob)
  737. domain = VMW_BO_DOMAIN_MOB;
  738. vmw_bo_placement_set(bo, domain, domain);
  739. }
  740. int vmw_bo_add_detached_resource(struct vmw_bo *vbo, struct vmw_resource *res)
  741. {
  742. return xa_err(xa_store(&vbo->detached_resources, (unsigned long)res, res, GFP_KERNEL));
  743. }
  744. void vmw_bo_del_detached_resource(struct vmw_bo *vbo, struct vmw_resource *res)
  745. {
  746. xa_erase(&vbo->detached_resources, (unsigned long)res);
  747. }
  748. struct vmw_surface *vmw_bo_surface(struct vmw_bo *vbo)
  749. {
  750. unsigned long index;
  751. struct vmw_resource *res = NULL;
  752. struct vmw_surface *surf = NULL;
  753. struct rb_node *rb_itr = vbo->res_tree.rb_node;
  754. if (vbo->is_dumb && vbo->dumb_surface) {
  755. res = &vbo->dumb_surface->res;
  756. goto out;
  757. }
  758. xa_for_each(&vbo->detached_resources, index, res) {
  759. if (res->func->res_type == vmw_res_surface)
  760. goto out;
  761. }
  762. for (rb_itr = rb_first(&vbo->res_tree); rb_itr;
  763. rb_itr = rb_next(rb_itr)) {
  764. res = rb_entry(rb_itr, struct vmw_resource, mob_node);
  765. if (res->func->res_type == vmw_res_surface)
  766. goto out;
  767. }
  768. out:
  769. if (res)
  770. surf = vmw_res_to_srf(res);
  771. return surf;
  772. }