vmwgfx_bo.c 23 KB

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