v3d_gem.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /* Copyright (C) 2014-2018 Broadcom */
  3. #include <drm/drmP.h>
  4. #include <drm/drm_syncobj.h>
  5. #include <linux/module.h>
  6. #include <linux/platform_device.h>
  7. #include <linux/pm_runtime.h>
  8. #include <linux/device.h>
  9. #include <linux/io.h>
  10. #include <linux/sched/signal.h>
  11. #include "uapi/drm/v3d_drm.h"
  12. #include "v3d_drv.h"
  13. #include "v3d_regs.h"
  14. #include "v3d_trace.h"
  15. static void
  16. v3d_init_core(struct v3d_dev *v3d, int core)
  17. {
  18. /* Set OVRTMUOUT, which means that the texture sampler uniform
  19. * configuration's tmu output type field is used, instead of
  20. * using the hardware default behavior based on the texture
  21. * type. If you want the default behavior, you can still put
  22. * "2" in the indirect texture state's output_type field.
  23. */
  24. V3D_CORE_WRITE(core, V3D_CTL_MISCCFG, V3D_MISCCFG_OVRTMUOUT);
  25. /* Whenever we flush the L2T cache, we always want to flush
  26. * the whole thing.
  27. */
  28. V3D_CORE_WRITE(core, V3D_CTL_L2TFLSTA, 0);
  29. V3D_CORE_WRITE(core, V3D_CTL_L2TFLEND, ~0);
  30. }
  31. /* Sets invariant state for the HW. */
  32. static void
  33. v3d_init_hw_state(struct v3d_dev *v3d)
  34. {
  35. v3d_init_core(v3d, 0);
  36. }
  37. static void
  38. v3d_idle_axi(struct v3d_dev *v3d, int core)
  39. {
  40. V3D_CORE_WRITE(core, V3D_GMP_CFG, V3D_GMP_CFG_STOP_REQ);
  41. if (wait_for((V3D_CORE_READ(core, V3D_GMP_STATUS) &
  42. (V3D_GMP_STATUS_RD_COUNT_MASK |
  43. V3D_GMP_STATUS_WR_COUNT_MASK |
  44. V3D_GMP_STATUS_CFG_BUSY)) == 0, 100)) {
  45. DRM_ERROR("Failed to wait for safe GMP shutdown\n");
  46. }
  47. }
  48. static void
  49. v3d_idle_gca(struct v3d_dev *v3d)
  50. {
  51. if (v3d->ver >= 41)
  52. return;
  53. V3D_GCA_WRITE(V3D_GCA_SAFE_SHUTDOWN, V3D_GCA_SAFE_SHUTDOWN_EN);
  54. if (wait_for((V3D_GCA_READ(V3D_GCA_SAFE_SHUTDOWN_ACK) &
  55. V3D_GCA_SAFE_SHUTDOWN_ACK_ACKED) ==
  56. V3D_GCA_SAFE_SHUTDOWN_ACK_ACKED, 100)) {
  57. DRM_ERROR("Failed to wait for safe GCA shutdown\n");
  58. }
  59. }
  60. static void
  61. v3d_reset_v3d(struct v3d_dev *v3d)
  62. {
  63. int version = V3D_BRIDGE_READ(V3D_TOP_GR_BRIDGE_REVISION);
  64. if (V3D_GET_FIELD(version, V3D_TOP_GR_BRIDGE_MAJOR) == 2) {
  65. V3D_BRIDGE_WRITE(V3D_TOP_GR_BRIDGE_SW_INIT_0,
  66. V3D_TOP_GR_BRIDGE_SW_INIT_0_V3D_CLK_108_SW_INIT);
  67. V3D_BRIDGE_WRITE(V3D_TOP_GR_BRIDGE_SW_INIT_0, 0);
  68. /* GFXH-1383: The SW_INIT may cause a stray write to address 0
  69. * of the unit, so reset it to its power-on value here.
  70. */
  71. V3D_WRITE(V3D_HUB_AXICFG, V3D_HUB_AXICFG_MAX_LEN_MASK);
  72. } else {
  73. WARN_ON_ONCE(V3D_GET_FIELD(version,
  74. V3D_TOP_GR_BRIDGE_MAJOR) != 7);
  75. V3D_BRIDGE_WRITE(V3D_TOP_GR_BRIDGE_SW_INIT_1,
  76. V3D_TOP_GR_BRIDGE_SW_INIT_1_V3D_CLK_108_SW_INIT);
  77. V3D_BRIDGE_WRITE(V3D_TOP_GR_BRIDGE_SW_INIT_1, 0);
  78. }
  79. v3d_init_hw_state(v3d);
  80. }
  81. void
  82. v3d_reset(struct v3d_dev *v3d)
  83. {
  84. struct drm_device *dev = &v3d->drm;
  85. DRM_ERROR("Resetting GPU.\n");
  86. trace_v3d_reset_begin(dev);
  87. /* XXX: only needed for safe powerdown, not reset. */
  88. if (false)
  89. v3d_idle_axi(v3d, 0);
  90. v3d_idle_gca(v3d);
  91. v3d_reset_v3d(v3d);
  92. v3d_mmu_set_page_table(v3d);
  93. v3d_irq_reset(v3d);
  94. trace_v3d_reset_end(dev);
  95. }
  96. static void
  97. v3d_flush_l3(struct v3d_dev *v3d)
  98. {
  99. if (v3d->ver < 41) {
  100. u32 gca_ctrl = V3D_GCA_READ(V3D_GCA_CACHE_CTRL);
  101. V3D_GCA_WRITE(V3D_GCA_CACHE_CTRL,
  102. gca_ctrl | V3D_GCA_CACHE_CTRL_FLUSH);
  103. if (v3d->ver < 33) {
  104. V3D_GCA_WRITE(V3D_GCA_CACHE_CTRL,
  105. gca_ctrl & ~V3D_GCA_CACHE_CTRL_FLUSH);
  106. }
  107. }
  108. }
  109. /* Invalidates the (read-only) L2 cache. */
  110. static void
  111. v3d_invalidate_l2(struct v3d_dev *v3d, int core)
  112. {
  113. V3D_CORE_WRITE(core, V3D_CTL_L2CACTL,
  114. V3D_L2CACTL_L2CCLR |
  115. V3D_L2CACTL_L2CENA);
  116. }
  117. static void
  118. v3d_invalidate_l1td(struct v3d_dev *v3d, int core)
  119. {
  120. V3D_CORE_WRITE(core, V3D_CTL_L2TCACTL, V3D_L2TCACTL_TMUWCF);
  121. if (wait_for(!(V3D_CORE_READ(core, V3D_CTL_L2TCACTL) &
  122. V3D_L2TCACTL_L2TFLS), 100)) {
  123. DRM_ERROR("Timeout waiting for L1T write combiner flush\n");
  124. }
  125. }
  126. /* Invalidates texture L2 cachelines */
  127. static void
  128. v3d_flush_l2t(struct v3d_dev *v3d, int core)
  129. {
  130. v3d_invalidate_l1td(v3d, core);
  131. V3D_CORE_WRITE(core, V3D_CTL_L2TCACTL,
  132. V3D_L2TCACTL_L2TFLS |
  133. V3D_SET_FIELD(V3D_L2TCACTL_FLM_FLUSH, V3D_L2TCACTL_FLM));
  134. if (wait_for(!(V3D_CORE_READ(core, V3D_CTL_L2TCACTL) &
  135. V3D_L2TCACTL_L2TFLS), 100)) {
  136. DRM_ERROR("Timeout waiting for L2T flush\n");
  137. }
  138. }
  139. /* Invalidates the slice caches. These are read-only caches. */
  140. static void
  141. v3d_invalidate_slices(struct v3d_dev *v3d, int core)
  142. {
  143. V3D_CORE_WRITE(core, V3D_CTL_SLCACTL,
  144. V3D_SET_FIELD(0xf, V3D_SLCACTL_TVCCS) |
  145. V3D_SET_FIELD(0xf, V3D_SLCACTL_TDCCS) |
  146. V3D_SET_FIELD(0xf, V3D_SLCACTL_UCC) |
  147. V3D_SET_FIELD(0xf, V3D_SLCACTL_ICC));
  148. }
  149. /* Invalidates texture L2 cachelines */
  150. static void
  151. v3d_invalidate_l2t(struct v3d_dev *v3d, int core)
  152. {
  153. V3D_CORE_WRITE(core,
  154. V3D_CTL_L2TCACTL,
  155. V3D_L2TCACTL_L2TFLS |
  156. V3D_SET_FIELD(V3D_L2TCACTL_FLM_CLEAR, V3D_L2TCACTL_FLM));
  157. if (wait_for(!(V3D_CORE_READ(core, V3D_CTL_L2TCACTL) &
  158. V3D_L2TCACTL_L2TFLS), 100)) {
  159. DRM_ERROR("Timeout waiting for L2T invalidate\n");
  160. }
  161. }
  162. void
  163. v3d_invalidate_caches(struct v3d_dev *v3d)
  164. {
  165. v3d_flush_l3(v3d);
  166. v3d_invalidate_l2(v3d, 0);
  167. v3d_invalidate_slices(v3d, 0);
  168. v3d_flush_l2t(v3d, 0);
  169. }
  170. void
  171. v3d_flush_caches(struct v3d_dev *v3d)
  172. {
  173. v3d_invalidate_l1td(v3d, 0);
  174. v3d_invalidate_l2t(v3d, 0);
  175. }
  176. static void
  177. v3d_attach_object_fences(struct v3d_exec_info *exec)
  178. {
  179. struct dma_fence *out_fence = &exec->render.base.s_fence->finished;
  180. struct v3d_bo *bo;
  181. int i;
  182. for (i = 0; i < exec->bo_count; i++) {
  183. bo = to_v3d_bo(&exec->bo[i]->base);
  184. /* XXX: Use shared fences for read-only objects. */
  185. reservation_object_add_excl_fence(bo->resv, out_fence);
  186. }
  187. }
  188. static void
  189. v3d_unlock_bo_reservations(struct drm_device *dev,
  190. struct v3d_exec_info *exec,
  191. struct ww_acquire_ctx *acquire_ctx)
  192. {
  193. int i;
  194. for (i = 0; i < exec->bo_count; i++) {
  195. struct v3d_bo *bo = to_v3d_bo(&exec->bo[i]->base);
  196. ww_mutex_unlock(&bo->resv->lock);
  197. }
  198. ww_acquire_fini(acquire_ctx);
  199. }
  200. /* Takes the reservation lock on all the BOs being referenced, so that
  201. * at queue submit time we can update the reservations.
  202. *
  203. * We don't lock the RCL the tile alloc/state BOs, or overflow memory
  204. * (all of which are on exec->unref_list). They're entirely private
  205. * to v3d, so we don't attach dma-buf fences to them.
  206. */
  207. static int
  208. v3d_lock_bo_reservations(struct drm_device *dev,
  209. struct v3d_exec_info *exec,
  210. struct ww_acquire_ctx *acquire_ctx)
  211. {
  212. int contended_lock = -1;
  213. int i, ret;
  214. struct v3d_bo *bo;
  215. ww_acquire_init(acquire_ctx, &reservation_ww_class);
  216. retry:
  217. if (contended_lock != -1) {
  218. bo = to_v3d_bo(&exec->bo[contended_lock]->base);
  219. ret = ww_mutex_lock_slow_interruptible(&bo->resv->lock,
  220. acquire_ctx);
  221. if (ret) {
  222. ww_acquire_done(acquire_ctx);
  223. return ret;
  224. }
  225. }
  226. for (i = 0; i < exec->bo_count; i++) {
  227. if (i == contended_lock)
  228. continue;
  229. bo = to_v3d_bo(&exec->bo[i]->base);
  230. ret = ww_mutex_lock_interruptible(&bo->resv->lock, acquire_ctx);
  231. if (ret) {
  232. int j;
  233. for (j = 0; j < i; j++) {
  234. bo = to_v3d_bo(&exec->bo[j]->base);
  235. ww_mutex_unlock(&bo->resv->lock);
  236. }
  237. if (contended_lock != -1 && contended_lock >= i) {
  238. bo = to_v3d_bo(&exec->bo[contended_lock]->base);
  239. ww_mutex_unlock(&bo->resv->lock);
  240. }
  241. if (ret == -EDEADLK) {
  242. contended_lock = i;
  243. goto retry;
  244. }
  245. ww_acquire_done(acquire_ctx);
  246. return ret;
  247. }
  248. }
  249. ww_acquire_done(acquire_ctx);
  250. /* Reserve space for our shared (read-only) fence references,
  251. * before we commit the CL to the hardware.
  252. */
  253. for (i = 0; i < exec->bo_count; i++) {
  254. bo = to_v3d_bo(&exec->bo[i]->base);
  255. ret = reservation_object_reserve_shared(bo->resv);
  256. if (ret) {
  257. v3d_unlock_bo_reservations(dev, exec, acquire_ctx);
  258. return ret;
  259. }
  260. }
  261. return 0;
  262. }
  263. /**
  264. * v3d_cl_lookup_bos() - Sets up exec->bo[] with the GEM objects
  265. * referenced by the job.
  266. * @dev: DRM device
  267. * @file_priv: DRM file for this fd
  268. * @exec: V3D job being set up
  269. *
  270. * The command validator needs to reference BOs by their index within
  271. * the submitted job's BO list. This does the validation of the job's
  272. * BO list and reference counting for the lifetime of the job.
  273. *
  274. * Note that this function doesn't need to unreference the BOs on
  275. * failure, because that will happen at v3d_exec_cleanup() time.
  276. */
  277. static int
  278. v3d_cl_lookup_bos(struct drm_device *dev,
  279. struct drm_file *file_priv,
  280. struct drm_v3d_submit_cl *args,
  281. struct v3d_exec_info *exec)
  282. {
  283. u32 *handles;
  284. int ret = 0;
  285. int i;
  286. exec->bo_count = args->bo_handle_count;
  287. if (!exec->bo_count) {
  288. /* See comment on bo_index for why we have to check
  289. * this.
  290. */
  291. DRM_DEBUG("Rendering requires BOs\n");
  292. return -EINVAL;
  293. }
  294. exec->bo = kvmalloc_array(exec->bo_count,
  295. sizeof(struct drm_gem_cma_object *),
  296. GFP_KERNEL | __GFP_ZERO);
  297. if (!exec->bo) {
  298. DRM_DEBUG("Failed to allocate validated BO pointers\n");
  299. return -ENOMEM;
  300. }
  301. handles = kvmalloc_array(exec->bo_count, sizeof(u32), GFP_KERNEL);
  302. if (!handles) {
  303. ret = -ENOMEM;
  304. DRM_DEBUG("Failed to allocate incoming GEM handles\n");
  305. goto fail;
  306. }
  307. if (copy_from_user(handles,
  308. (void __user *)(uintptr_t)args->bo_handles,
  309. exec->bo_count * sizeof(u32))) {
  310. ret = -EFAULT;
  311. DRM_DEBUG("Failed to copy in GEM handles\n");
  312. goto fail;
  313. }
  314. spin_lock(&file_priv->table_lock);
  315. for (i = 0; i < exec->bo_count; i++) {
  316. struct drm_gem_object *bo = idr_find(&file_priv->object_idr,
  317. handles[i]);
  318. if (!bo) {
  319. DRM_DEBUG("Failed to look up GEM BO %d: %d\n",
  320. i, handles[i]);
  321. ret = -ENOENT;
  322. spin_unlock(&file_priv->table_lock);
  323. goto fail;
  324. }
  325. drm_gem_object_get(bo);
  326. exec->bo[i] = to_v3d_bo(bo);
  327. }
  328. spin_unlock(&file_priv->table_lock);
  329. fail:
  330. kvfree(handles);
  331. return ret;
  332. }
  333. static void
  334. v3d_exec_cleanup(struct kref *ref)
  335. {
  336. struct v3d_exec_info *exec = container_of(ref, struct v3d_exec_info,
  337. refcount);
  338. struct v3d_dev *v3d = exec->v3d;
  339. unsigned int i;
  340. struct v3d_bo *bo, *save;
  341. dma_fence_put(exec->bin.in_fence);
  342. dma_fence_put(exec->render.in_fence);
  343. dma_fence_put(exec->bin.done_fence);
  344. dma_fence_put(exec->render.done_fence);
  345. dma_fence_put(exec->bin_done_fence);
  346. for (i = 0; i < exec->bo_count; i++)
  347. drm_gem_object_put_unlocked(&exec->bo[i]->base);
  348. kvfree(exec->bo);
  349. list_for_each_entry_safe(bo, save, &exec->unref_list, unref_head) {
  350. drm_gem_object_put_unlocked(&bo->base);
  351. }
  352. pm_runtime_mark_last_busy(v3d->dev);
  353. pm_runtime_put_autosuspend(v3d->dev);
  354. kfree(exec);
  355. }
  356. void v3d_exec_put(struct v3d_exec_info *exec)
  357. {
  358. kref_put(&exec->refcount, v3d_exec_cleanup);
  359. }
  360. int
  361. v3d_wait_bo_ioctl(struct drm_device *dev, void *data,
  362. struct drm_file *file_priv)
  363. {
  364. int ret;
  365. struct drm_v3d_wait_bo *args = data;
  366. struct drm_gem_object *gem_obj;
  367. struct v3d_bo *bo;
  368. ktime_t start = ktime_get();
  369. u64 delta_ns;
  370. unsigned long timeout_jiffies =
  371. nsecs_to_jiffies_timeout(args->timeout_ns);
  372. if (args->pad != 0)
  373. return -EINVAL;
  374. gem_obj = drm_gem_object_lookup(file_priv, args->handle);
  375. if (!gem_obj) {
  376. DRM_DEBUG("Failed to look up GEM BO %d\n", args->handle);
  377. return -EINVAL;
  378. }
  379. bo = to_v3d_bo(gem_obj);
  380. ret = reservation_object_wait_timeout_rcu(bo->resv,
  381. true, true,
  382. timeout_jiffies);
  383. if (ret == 0)
  384. ret = -ETIME;
  385. else if (ret > 0)
  386. ret = 0;
  387. /* Decrement the user's timeout, in case we got interrupted
  388. * such that the ioctl will be restarted.
  389. */
  390. delta_ns = ktime_to_ns(ktime_sub(ktime_get(), start));
  391. if (delta_ns < args->timeout_ns)
  392. args->timeout_ns -= delta_ns;
  393. else
  394. args->timeout_ns = 0;
  395. /* Asked to wait beyond the jiffie/scheduler precision? */
  396. if (ret == -ETIME && args->timeout_ns)
  397. ret = -EAGAIN;
  398. drm_gem_object_put_unlocked(gem_obj);
  399. return ret;
  400. }
  401. /**
  402. * v3d_submit_cl_ioctl() - Submits a job (frame) to the V3D.
  403. * @dev: DRM device
  404. * @data: ioctl argument
  405. * @file_priv: DRM file for this fd
  406. *
  407. * This is the main entrypoint for userspace to submit a 3D frame to
  408. * the GPU. Userspace provides the binner command list (if
  409. * applicable), and the kernel sets up the render command list to draw
  410. * to the framebuffer described in the ioctl, using the command lists
  411. * that the 3D engine's binner will produce.
  412. */
  413. int
  414. v3d_submit_cl_ioctl(struct drm_device *dev, void *data,
  415. struct drm_file *file_priv)
  416. {
  417. struct v3d_dev *v3d = to_v3d_dev(dev);
  418. struct v3d_file_priv *v3d_priv = file_priv->driver_priv;
  419. struct drm_v3d_submit_cl *args = data;
  420. struct v3d_exec_info *exec;
  421. struct ww_acquire_ctx acquire_ctx;
  422. struct drm_syncobj *sync_out;
  423. int ret = 0;
  424. if (args->pad != 0) {
  425. DRM_INFO("pad must be zero: %d\n", args->pad);
  426. return -EINVAL;
  427. }
  428. exec = kcalloc(1, sizeof(*exec), GFP_KERNEL);
  429. if (!exec)
  430. return -ENOMEM;
  431. ret = pm_runtime_get_sync(v3d->dev);
  432. if (ret < 0) {
  433. kfree(exec);
  434. return ret;
  435. }
  436. kref_init(&exec->refcount);
  437. ret = drm_syncobj_find_fence(file_priv, args->in_sync_bcl,
  438. &exec->bin.in_fence);
  439. if (ret == -EINVAL)
  440. goto fail;
  441. ret = drm_syncobj_find_fence(file_priv, args->in_sync_rcl,
  442. &exec->render.in_fence);
  443. if (ret == -EINVAL)
  444. goto fail;
  445. exec->qma = args->qma;
  446. exec->qms = args->qms;
  447. exec->qts = args->qts;
  448. exec->bin.exec = exec;
  449. exec->bin.start = args->bcl_start;
  450. exec->bin.end = args->bcl_end;
  451. exec->render.exec = exec;
  452. exec->render.start = args->rcl_start;
  453. exec->render.end = args->rcl_end;
  454. exec->v3d = v3d;
  455. INIT_LIST_HEAD(&exec->unref_list);
  456. ret = v3d_cl_lookup_bos(dev, file_priv, args, exec);
  457. if (ret)
  458. goto fail;
  459. ret = v3d_lock_bo_reservations(dev, exec, &acquire_ctx);
  460. if (ret)
  461. goto fail;
  462. mutex_lock(&v3d->sched_lock);
  463. if (exec->bin.start != exec->bin.end) {
  464. ret = drm_sched_job_init(&exec->bin.base,
  465. &v3d_priv->sched_entity[V3D_BIN],
  466. v3d_priv);
  467. if (ret)
  468. goto fail_unreserve;
  469. exec->bin_done_fence =
  470. dma_fence_get(&exec->bin.base.s_fence->finished);
  471. kref_get(&exec->refcount); /* put by scheduler job completion */
  472. drm_sched_entity_push_job(&exec->bin.base,
  473. &v3d_priv->sched_entity[V3D_BIN]);
  474. }
  475. ret = drm_sched_job_init(&exec->render.base,
  476. &v3d_priv->sched_entity[V3D_RENDER],
  477. v3d_priv);
  478. if (ret)
  479. goto fail_unreserve;
  480. kref_get(&exec->refcount); /* put by scheduler job completion */
  481. drm_sched_entity_push_job(&exec->render.base,
  482. &v3d_priv->sched_entity[V3D_RENDER]);
  483. mutex_unlock(&v3d->sched_lock);
  484. v3d_attach_object_fences(exec);
  485. v3d_unlock_bo_reservations(dev, exec, &acquire_ctx);
  486. /* Update the return sync object for the */
  487. sync_out = drm_syncobj_find(file_priv, args->out_sync);
  488. if (sync_out) {
  489. drm_syncobj_replace_fence(sync_out,
  490. &exec->render.base.s_fence->finished);
  491. drm_syncobj_put(sync_out);
  492. }
  493. v3d_exec_put(exec);
  494. return 0;
  495. fail_unreserve:
  496. mutex_unlock(&v3d->sched_lock);
  497. v3d_unlock_bo_reservations(dev, exec, &acquire_ctx);
  498. fail:
  499. v3d_exec_put(exec);
  500. return ret;
  501. }
  502. int
  503. v3d_gem_init(struct drm_device *dev)
  504. {
  505. struct v3d_dev *v3d = to_v3d_dev(dev);
  506. u32 pt_size = 4096 * 1024;
  507. int ret, i;
  508. for (i = 0; i < V3D_MAX_QUEUES; i++)
  509. v3d->queue[i].fence_context = dma_fence_context_alloc(1);
  510. spin_lock_init(&v3d->mm_lock);
  511. spin_lock_init(&v3d->job_lock);
  512. mutex_init(&v3d->bo_lock);
  513. mutex_init(&v3d->reset_lock);
  514. mutex_init(&v3d->sched_lock);
  515. /* Note: We don't allocate address 0. Various bits of HW
  516. * treat 0 as special, such as the occlusion query counters
  517. * where 0 means "disabled".
  518. */
  519. drm_mm_init(&v3d->mm, 1, pt_size / sizeof(u32) - 1);
  520. v3d->pt = dma_alloc_wc(v3d->dev, pt_size,
  521. &v3d->pt_paddr,
  522. GFP_KERNEL | __GFP_NOWARN | __GFP_ZERO);
  523. if (!v3d->pt) {
  524. drm_mm_takedown(&v3d->mm);
  525. dev_err(v3d->dev,
  526. "Failed to allocate page tables. "
  527. "Please ensure you have CMA enabled.\n");
  528. return -ENOMEM;
  529. }
  530. v3d_init_hw_state(v3d);
  531. v3d_mmu_set_page_table(v3d);
  532. ret = v3d_sched_init(v3d);
  533. if (ret) {
  534. drm_mm_takedown(&v3d->mm);
  535. dma_free_coherent(v3d->dev, 4096 * 1024, (void *)v3d->pt,
  536. v3d->pt_paddr);
  537. }
  538. return 0;
  539. }
  540. void
  541. v3d_gem_destroy(struct drm_device *dev)
  542. {
  543. struct v3d_dev *v3d = to_v3d_dev(dev);
  544. v3d_sched_fini(v3d);
  545. /* Waiting for exec to finish would need to be done before
  546. * unregistering V3D.
  547. */
  548. WARN_ON(v3d->bin_job);
  549. WARN_ON(v3d->render_job);
  550. drm_mm_takedown(&v3d->mm);
  551. dma_free_coherent(v3d->dev, 4096 * 1024, (void *)v3d->pt, v3d->pt_paddr);
  552. }