msm_gem_submit.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (C) 2013 Red Hat
  4. * Author: Rob Clark <robdclark@gmail.com>
  5. */
  6. #include <linux/file.h>
  7. #include <linux/sync_file.h>
  8. #include <linux/uaccess.h>
  9. #include <drm/drm_drv.h>
  10. #include <drm/drm_file.h>
  11. #include <drm/drm_syncobj.h>
  12. #include "msm_drv.h"
  13. #include "msm_gpu.h"
  14. #include "msm_gem.h"
  15. #include "msm_gpu_trace.h"
  16. /* For userspace errors, use DRM_UT_DRIVER.. so that userspace can enable
  17. * error msgs for debugging, but we don't spam dmesg by default
  18. */
  19. #define SUBMIT_ERROR(submit, fmt, ...) \
  20. DRM_DEV_DEBUG_DRIVER((submit)->dev->dev, fmt, ##__VA_ARGS__)
  21. /*
  22. * Cmdstream submission:
  23. */
  24. static struct msm_gem_submit *submit_create(struct drm_device *dev,
  25. struct msm_gpu *gpu,
  26. struct msm_gpu_submitqueue *queue, uint32_t nr_bos,
  27. uint32_t nr_cmds)
  28. {
  29. static atomic_t ident = ATOMIC_INIT(0);
  30. struct msm_gem_submit *submit;
  31. uint64_t sz;
  32. int ret;
  33. sz = struct_size(submit, bos, nr_bos) +
  34. ((u64)nr_cmds * sizeof(submit->cmd[0]));
  35. if (sz > SIZE_MAX)
  36. return ERR_PTR(-ENOMEM);
  37. submit = kzalloc(sz, GFP_KERNEL | __GFP_NOWARN);
  38. if (!submit)
  39. return ERR_PTR(-ENOMEM);
  40. submit->hw_fence = msm_fence_alloc();
  41. if (IS_ERR(submit->hw_fence)) {
  42. ret = PTR_ERR(submit->hw_fence);
  43. kfree(submit);
  44. return ERR_PTR(ret);
  45. }
  46. ret = drm_sched_job_init(&submit->base, queue->entity, 1, queue);
  47. if (ret) {
  48. kfree(submit->hw_fence);
  49. kfree(submit);
  50. return ERR_PTR(ret);
  51. }
  52. kref_init(&submit->ref);
  53. submit->dev = dev;
  54. submit->aspace = queue->ctx->aspace;
  55. submit->gpu = gpu;
  56. submit->cmd = (void *)&submit->bos[nr_bos];
  57. submit->queue = queue;
  58. submit->pid = get_pid(task_pid(current));
  59. submit->ring = gpu->rb[queue->ring_nr];
  60. submit->fault_dumped = false;
  61. /* Get a unique identifier for the submission for logging purposes */
  62. submit->ident = atomic_inc_return(&ident) - 1;
  63. INIT_LIST_HEAD(&submit->node);
  64. return submit;
  65. }
  66. void __msm_gem_submit_destroy(struct kref *kref)
  67. {
  68. struct msm_gem_submit *submit =
  69. container_of(kref, struct msm_gem_submit, ref);
  70. unsigned i;
  71. /*
  72. * In error paths, we could unref the submit without calling
  73. * drm_sched_entity_push_job(), so msm_job_free() will never
  74. * get called. Since drm_sched_job_cleanup() will NULL out
  75. * s_fence, we can use that to detect this case.
  76. */
  77. if (submit->base.s_fence)
  78. drm_sched_job_cleanup(&submit->base);
  79. if (submit->fence_id) {
  80. spin_lock(&submit->queue->idr_lock);
  81. idr_remove(&submit->queue->fence_idr, submit->fence_id);
  82. spin_unlock(&submit->queue->idr_lock);
  83. }
  84. dma_fence_put(submit->user_fence);
  85. /*
  86. * If the submit is freed before msm_job_run(), then hw_fence is
  87. * just some pre-allocated memory, not a reference counted fence.
  88. * Once the job runs and the hw_fence is initialized, it will
  89. * have a refcount of at least one, since the submit holds a ref
  90. * to the hw_fence.
  91. */
  92. if (kref_read(&submit->hw_fence->refcount) == 0) {
  93. kfree(submit->hw_fence);
  94. } else {
  95. dma_fence_put(submit->hw_fence);
  96. }
  97. put_pid(submit->pid);
  98. msm_submitqueue_put(submit->queue);
  99. for (i = 0; i < submit->nr_cmds; i++)
  100. kfree(submit->cmd[i].relocs);
  101. kfree(submit);
  102. }
  103. static int submit_lookup_objects(struct msm_gem_submit *submit,
  104. struct drm_msm_gem_submit *args, struct drm_file *file)
  105. {
  106. unsigned i;
  107. int ret = 0;
  108. for (i = 0; i < args->nr_bos; i++) {
  109. struct drm_msm_gem_submit_bo submit_bo;
  110. void __user *userptr =
  111. u64_to_user_ptr(args->bos + (i * sizeof(submit_bo)));
  112. /* make sure we don't have garbage flags, in case we hit
  113. * error path before flags is initialized:
  114. */
  115. submit->bos[i].flags = 0;
  116. if (copy_from_user(&submit_bo, userptr, sizeof(submit_bo))) {
  117. ret = -EFAULT;
  118. i = 0;
  119. goto out;
  120. }
  121. /* at least one of READ and/or WRITE flags should be set: */
  122. #define MANDATORY_FLAGS (MSM_SUBMIT_BO_READ | MSM_SUBMIT_BO_WRITE)
  123. if ((submit_bo.flags & ~MSM_SUBMIT_BO_FLAGS) ||
  124. !(submit_bo.flags & MANDATORY_FLAGS)) {
  125. SUBMIT_ERROR(submit, "invalid flags: %x\n", submit_bo.flags);
  126. ret = -EINVAL;
  127. i = 0;
  128. goto out;
  129. }
  130. submit->bos[i].handle = submit_bo.handle;
  131. submit->bos[i].flags = submit_bo.flags;
  132. }
  133. spin_lock(&file->table_lock);
  134. for (i = 0; i < args->nr_bos; i++) {
  135. struct drm_gem_object *obj;
  136. /* normally use drm_gem_object_lookup(), but for bulk lookup
  137. * all under single table_lock just hit object_idr directly:
  138. */
  139. obj = idr_find(&file->object_idr, submit->bos[i].handle);
  140. if (!obj) {
  141. SUBMIT_ERROR(submit, "invalid handle %u at index %u\n", submit->bos[i].handle, i);
  142. ret = -EINVAL;
  143. goto out_unlock;
  144. }
  145. drm_gem_object_get(obj);
  146. submit->bos[i].obj = obj;
  147. }
  148. out_unlock:
  149. spin_unlock(&file->table_lock);
  150. out:
  151. submit->nr_bos = i;
  152. return ret;
  153. }
  154. static int submit_lookup_cmds(struct msm_gem_submit *submit,
  155. struct drm_msm_gem_submit *args, struct drm_file *file)
  156. {
  157. unsigned i;
  158. size_t sz;
  159. int ret = 0;
  160. for (i = 0; i < args->nr_cmds; i++) {
  161. struct drm_msm_gem_submit_cmd submit_cmd;
  162. void __user *userptr =
  163. u64_to_user_ptr(args->cmds + (i * sizeof(submit_cmd)));
  164. ret = copy_from_user(&submit_cmd, userptr, sizeof(submit_cmd));
  165. if (ret) {
  166. ret = -EFAULT;
  167. goto out;
  168. }
  169. /* validate input from userspace: */
  170. switch (submit_cmd.type) {
  171. case MSM_SUBMIT_CMD_BUF:
  172. case MSM_SUBMIT_CMD_IB_TARGET_BUF:
  173. case MSM_SUBMIT_CMD_CTX_RESTORE_BUF:
  174. break;
  175. default:
  176. SUBMIT_ERROR(submit, "invalid type: %08x\n", submit_cmd.type);
  177. return -EINVAL;
  178. }
  179. if (submit_cmd.size % 4) {
  180. SUBMIT_ERROR(submit, "non-aligned cmdstream buffer size: %u\n",
  181. submit_cmd.size);
  182. ret = -EINVAL;
  183. goto out;
  184. }
  185. submit->cmd[i].type = submit_cmd.type;
  186. submit->cmd[i].size = submit_cmd.size / 4;
  187. submit->cmd[i].offset = submit_cmd.submit_offset / 4;
  188. submit->cmd[i].idx = submit_cmd.submit_idx;
  189. submit->cmd[i].nr_relocs = submit_cmd.nr_relocs;
  190. userptr = u64_to_user_ptr(submit_cmd.relocs);
  191. sz = array_size(submit_cmd.nr_relocs,
  192. sizeof(struct drm_msm_gem_submit_reloc));
  193. /* check for overflow: */
  194. if (sz == SIZE_MAX) {
  195. ret = -ENOMEM;
  196. goto out;
  197. }
  198. submit->cmd[i].relocs = kmalloc(sz, GFP_KERNEL | __GFP_NOWARN);
  199. if (!submit->cmd[i].relocs) {
  200. ret = -ENOMEM;
  201. goto out;
  202. }
  203. ret = copy_from_user(submit->cmd[i].relocs, userptr, sz);
  204. if (ret) {
  205. ret = -EFAULT;
  206. goto out;
  207. }
  208. }
  209. out:
  210. return ret;
  211. }
  212. /* This is where we make sure all the bo's are reserved and pin'd: */
  213. static int submit_lock_objects(struct msm_gem_submit *submit)
  214. {
  215. int ret;
  216. drm_exec_init(&submit->exec, DRM_EXEC_INTERRUPTIBLE_WAIT, submit->nr_bos);
  217. drm_exec_until_all_locked (&submit->exec) {
  218. for (unsigned i = 0; i < submit->nr_bos; i++) {
  219. struct drm_gem_object *obj = submit->bos[i].obj;
  220. ret = drm_exec_prepare_obj(&submit->exec, obj, 1);
  221. drm_exec_retry_on_contention(&submit->exec);
  222. if (ret)
  223. goto error;
  224. }
  225. }
  226. return 0;
  227. error:
  228. return ret;
  229. }
  230. static int submit_fence_sync(struct msm_gem_submit *submit)
  231. {
  232. int i, ret = 0;
  233. for (i = 0; i < submit->nr_bos; i++) {
  234. struct drm_gem_object *obj = submit->bos[i].obj;
  235. bool write = submit->bos[i].flags & MSM_SUBMIT_BO_WRITE;
  236. /* Otherwise userspace can ask for implicit sync to be
  237. * disabled on specific buffers. This is useful for internal
  238. * usermode driver managed buffers, suballocation, etc.
  239. */
  240. if (submit->bos[i].flags & MSM_SUBMIT_BO_NO_IMPLICIT)
  241. continue;
  242. ret = drm_sched_job_add_implicit_dependencies(&submit->base,
  243. obj,
  244. write);
  245. if (ret)
  246. break;
  247. }
  248. return ret;
  249. }
  250. static int submit_pin_objects(struct msm_gem_submit *submit)
  251. {
  252. struct msm_drm_private *priv = submit->dev->dev_private;
  253. int i, ret = 0;
  254. for (i = 0; i < submit->nr_bos; i++) {
  255. struct drm_gem_object *obj = submit->bos[i].obj;
  256. struct msm_gem_vma *vma;
  257. /* if locking succeeded, pin bo: */
  258. vma = msm_gem_get_vma_locked(obj, submit->aspace);
  259. if (IS_ERR(vma)) {
  260. ret = PTR_ERR(vma);
  261. break;
  262. }
  263. ret = msm_gem_pin_vma_locked(obj, vma);
  264. if (ret)
  265. break;
  266. submit->bos[i].iova = vma->iova;
  267. }
  268. /*
  269. * A second loop while holding the LRU lock (a) avoids acquiring/dropping
  270. * the LRU lock for each individual bo, while (b) avoiding holding the
  271. * LRU lock while calling msm_gem_pin_vma_locked() (which could trigger
  272. * get_pages() which could trigger reclaim.. and if we held the LRU lock
  273. * could trigger deadlock with the shrinker).
  274. */
  275. mutex_lock(&priv->lru.lock);
  276. for (i = 0; i < submit->nr_bos; i++) {
  277. msm_gem_pin_obj_locked(submit->bos[i].obj);
  278. }
  279. mutex_unlock(&priv->lru.lock);
  280. submit->bos_pinned = true;
  281. return ret;
  282. }
  283. static void submit_unpin_objects(struct msm_gem_submit *submit)
  284. {
  285. if (!submit->bos_pinned)
  286. return;
  287. for (int i = 0; i < submit->nr_bos; i++) {
  288. struct drm_gem_object *obj = submit->bos[i].obj;
  289. msm_gem_unpin_locked(obj);
  290. }
  291. submit->bos_pinned = false;
  292. }
  293. static void submit_attach_object_fences(struct msm_gem_submit *submit)
  294. {
  295. int i;
  296. for (i = 0; i < submit->nr_bos; i++) {
  297. struct drm_gem_object *obj = submit->bos[i].obj;
  298. if (submit->bos[i].flags & MSM_SUBMIT_BO_WRITE)
  299. dma_resv_add_fence(obj->resv, submit->user_fence,
  300. DMA_RESV_USAGE_WRITE);
  301. else if (submit->bos[i].flags & MSM_SUBMIT_BO_READ)
  302. dma_resv_add_fence(obj->resv, submit->user_fence,
  303. DMA_RESV_USAGE_READ);
  304. }
  305. }
  306. static int submit_bo(struct msm_gem_submit *submit, uint32_t idx,
  307. struct drm_gem_object **obj, uint64_t *iova)
  308. {
  309. if (idx >= submit->nr_bos) {
  310. SUBMIT_ERROR(submit, "invalid buffer index: %u (out of %u)\n",
  311. idx, submit->nr_bos);
  312. return -EINVAL;
  313. }
  314. if (obj)
  315. *obj = submit->bos[idx].obj;
  316. if (iova)
  317. *iova = submit->bos[idx].iova;
  318. return 0;
  319. }
  320. /* process the reloc's and patch up the cmdstream as needed: */
  321. static int submit_reloc(struct msm_gem_submit *submit, struct drm_gem_object *obj,
  322. uint32_t offset, uint32_t nr_relocs, struct drm_msm_gem_submit_reloc *relocs)
  323. {
  324. uint32_t i, last_offset = 0;
  325. uint32_t *ptr;
  326. int ret = 0;
  327. if (offset % 4) {
  328. SUBMIT_ERROR(submit, "non-aligned cmdstream buffer: %u\n", offset);
  329. return -EINVAL;
  330. }
  331. /* For now, just map the entire thing. Eventually we probably
  332. * to do it page-by-page, w/ kmap() if not vmap()d..
  333. */
  334. ptr = msm_gem_get_vaddr_locked(obj);
  335. if (IS_ERR(ptr)) {
  336. ret = PTR_ERR(ptr);
  337. DBG("failed to map: %d", ret);
  338. return ret;
  339. }
  340. for (i = 0; i < nr_relocs; i++) {
  341. struct drm_msm_gem_submit_reloc submit_reloc = relocs[i];
  342. uint32_t off;
  343. uint64_t iova;
  344. if (submit_reloc.submit_offset % 4) {
  345. SUBMIT_ERROR(submit, "non-aligned reloc offset: %u\n",
  346. submit_reloc.submit_offset);
  347. ret = -EINVAL;
  348. goto out;
  349. }
  350. /* offset in dwords: */
  351. off = submit_reloc.submit_offset / 4;
  352. if ((off >= (obj->size / 4)) ||
  353. (off < last_offset)) {
  354. SUBMIT_ERROR(submit, "invalid offset %u at reloc %u\n", off, i);
  355. ret = -EINVAL;
  356. goto out;
  357. }
  358. ret = submit_bo(submit, submit_reloc.reloc_idx, NULL, &iova);
  359. if (ret)
  360. goto out;
  361. iova += submit_reloc.reloc_offset;
  362. if (submit_reloc.shift < 0)
  363. iova >>= -submit_reloc.shift;
  364. else
  365. iova <<= submit_reloc.shift;
  366. ptr[off] = iova | submit_reloc.or;
  367. last_offset = off;
  368. }
  369. out:
  370. msm_gem_put_vaddr_locked(obj);
  371. return ret;
  372. }
  373. /* Cleanup submit at end of ioctl. In the error case, this also drops
  374. * references, unpins, and drops active refcnt. In the non-error case,
  375. * this is done when the submit is retired.
  376. */
  377. static void submit_cleanup(struct msm_gem_submit *submit, bool error)
  378. {
  379. if (error) {
  380. submit_unpin_objects(submit);
  381. /* job wasn't enqueued to scheduler, so early retirement: */
  382. msm_submit_retire(submit);
  383. }
  384. if (submit->exec.objects)
  385. drm_exec_fini(&submit->exec);
  386. }
  387. void msm_submit_retire(struct msm_gem_submit *submit)
  388. {
  389. int i;
  390. for (i = 0; i < submit->nr_bos; i++) {
  391. struct drm_gem_object *obj = submit->bos[i].obj;
  392. drm_gem_object_put(obj);
  393. }
  394. }
  395. struct msm_submit_post_dep {
  396. struct drm_syncobj *syncobj;
  397. uint64_t point;
  398. struct dma_fence_chain *chain;
  399. };
  400. static struct drm_syncobj **msm_parse_deps(struct msm_gem_submit *submit,
  401. struct drm_file *file,
  402. uint64_t in_syncobjs_addr,
  403. uint32_t nr_in_syncobjs,
  404. size_t syncobj_stride)
  405. {
  406. struct drm_syncobj **syncobjs = NULL;
  407. struct drm_msm_gem_submit_syncobj syncobj_desc = {0};
  408. int ret = 0;
  409. uint32_t i, j;
  410. syncobjs = kcalloc(nr_in_syncobjs, sizeof(*syncobjs),
  411. GFP_KERNEL | __GFP_NOWARN | __GFP_NORETRY);
  412. if (!syncobjs)
  413. return ERR_PTR(-ENOMEM);
  414. for (i = 0; i < nr_in_syncobjs; ++i) {
  415. uint64_t address = in_syncobjs_addr + i * syncobj_stride;
  416. if (copy_from_user(&syncobj_desc,
  417. u64_to_user_ptr(address),
  418. min(syncobj_stride, sizeof(syncobj_desc)))) {
  419. ret = -EFAULT;
  420. break;
  421. }
  422. if (syncobj_desc.point &&
  423. !drm_core_check_feature(submit->dev, DRIVER_SYNCOBJ_TIMELINE)) {
  424. ret = -EOPNOTSUPP;
  425. break;
  426. }
  427. if (syncobj_desc.flags & ~MSM_SUBMIT_SYNCOBJ_FLAGS) {
  428. ret = -EINVAL;
  429. break;
  430. }
  431. ret = drm_sched_job_add_syncobj_dependency(&submit->base, file,
  432. syncobj_desc.handle, syncobj_desc.point);
  433. if (ret)
  434. break;
  435. if (syncobj_desc.flags & MSM_SUBMIT_SYNCOBJ_RESET) {
  436. syncobjs[i] =
  437. drm_syncobj_find(file, syncobj_desc.handle);
  438. if (!syncobjs[i]) {
  439. ret = -EINVAL;
  440. break;
  441. }
  442. }
  443. }
  444. if (ret) {
  445. for (j = 0; j <= i; ++j) {
  446. if (syncobjs[j])
  447. drm_syncobj_put(syncobjs[j]);
  448. }
  449. kfree(syncobjs);
  450. return ERR_PTR(ret);
  451. }
  452. return syncobjs;
  453. }
  454. static void msm_reset_syncobjs(struct drm_syncobj **syncobjs,
  455. uint32_t nr_syncobjs)
  456. {
  457. uint32_t i;
  458. for (i = 0; syncobjs && i < nr_syncobjs; ++i) {
  459. if (syncobjs[i])
  460. drm_syncobj_replace_fence(syncobjs[i], NULL);
  461. }
  462. }
  463. static struct msm_submit_post_dep *msm_parse_post_deps(struct drm_device *dev,
  464. struct drm_file *file,
  465. uint64_t syncobjs_addr,
  466. uint32_t nr_syncobjs,
  467. size_t syncobj_stride)
  468. {
  469. struct msm_submit_post_dep *post_deps;
  470. struct drm_msm_gem_submit_syncobj syncobj_desc = {0};
  471. int ret = 0;
  472. uint32_t i, j;
  473. post_deps = kcalloc(nr_syncobjs, sizeof(*post_deps),
  474. GFP_KERNEL | __GFP_NOWARN | __GFP_NORETRY);
  475. if (!post_deps)
  476. return ERR_PTR(-ENOMEM);
  477. for (i = 0; i < nr_syncobjs; ++i) {
  478. uint64_t address = syncobjs_addr + i * syncobj_stride;
  479. if (copy_from_user(&syncobj_desc,
  480. u64_to_user_ptr(address),
  481. min(syncobj_stride, sizeof(syncobj_desc)))) {
  482. ret = -EFAULT;
  483. break;
  484. }
  485. post_deps[i].point = syncobj_desc.point;
  486. if (syncobj_desc.flags) {
  487. ret = -EINVAL;
  488. break;
  489. }
  490. if (syncobj_desc.point) {
  491. if (!drm_core_check_feature(dev,
  492. DRIVER_SYNCOBJ_TIMELINE)) {
  493. ret = -EOPNOTSUPP;
  494. break;
  495. }
  496. post_deps[i].chain = dma_fence_chain_alloc();
  497. if (!post_deps[i].chain) {
  498. ret = -ENOMEM;
  499. break;
  500. }
  501. }
  502. post_deps[i].syncobj =
  503. drm_syncobj_find(file, syncobj_desc.handle);
  504. if (!post_deps[i].syncobj) {
  505. ret = -EINVAL;
  506. break;
  507. }
  508. }
  509. if (ret) {
  510. for (j = 0; j <= i; ++j) {
  511. dma_fence_chain_free(post_deps[j].chain);
  512. if (post_deps[j].syncobj)
  513. drm_syncobj_put(post_deps[j].syncobj);
  514. }
  515. kfree(post_deps);
  516. return ERR_PTR(ret);
  517. }
  518. return post_deps;
  519. }
  520. static void msm_process_post_deps(struct msm_submit_post_dep *post_deps,
  521. uint32_t count, struct dma_fence *fence)
  522. {
  523. uint32_t i;
  524. for (i = 0; post_deps && i < count; ++i) {
  525. if (post_deps[i].chain) {
  526. drm_syncobj_add_point(post_deps[i].syncobj,
  527. post_deps[i].chain,
  528. fence, post_deps[i].point);
  529. post_deps[i].chain = NULL;
  530. } else {
  531. drm_syncobj_replace_fence(post_deps[i].syncobj,
  532. fence);
  533. }
  534. }
  535. }
  536. int msm_ioctl_gem_submit(struct drm_device *dev, void *data,
  537. struct drm_file *file)
  538. {
  539. struct msm_drm_private *priv = dev->dev_private;
  540. struct drm_msm_gem_submit *args = data;
  541. struct msm_file_private *ctx = file->driver_priv;
  542. struct msm_gem_submit *submit = NULL;
  543. struct msm_gpu *gpu = priv->gpu;
  544. struct msm_gpu_submitqueue *queue;
  545. struct msm_ringbuffer *ring;
  546. struct msm_submit_post_dep *post_deps = NULL;
  547. struct drm_syncobj **syncobjs_to_reset = NULL;
  548. struct sync_file *sync_file = NULL;
  549. int out_fence_fd = -1;
  550. unsigned i;
  551. int ret;
  552. if (!gpu)
  553. return -ENXIO;
  554. if (args->pad)
  555. return -EINVAL;
  556. if (unlikely(!ctx->aspace) && !capable(CAP_SYS_RAWIO)) {
  557. DRM_ERROR_RATELIMITED("IOMMU support or CAP_SYS_RAWIO required!\n");
  558. return -EPERM;
  559. }
  560. /* for now, we just have 3d pipe.. eventually this would need to
  561. * be more clever to dispatch to appropriate gpu module:
  562. */
  563. if (MSM_PIPE_ID(args->flags) != MSM_PIPE_3D0)
  564. return -EINVAL;
  565. if (MSM_PIPE_FLAGS(args->flags) & ~MSM_SUBMIT_FLAGS)
  566. return -EINVAL;
  567. if (args->flags & MSM_SUBMIT_SUDO) {
  568. if (!IS_ENABLED(CONFIG_DRM_MSM_GPU_SUDO) ||
  569. !capable(CAP_SYS_RAWIO))
  570. return -EINVAL;
  571. }
  572. queue = msm_submitqueue_get(ctx, args->queueid);
  573. if (!queue)
  574. return -ENOENT;
  575. ring = gpu->rb[queue->ring_nr];
  576. if (args->flags & MSM_SUBMIT_FENCE_FD_OUT) {
  577. out_fence_fd = get_unused_fd_flags(O_CLOEXEC);
  578. if (out_fence_fd < 0) {
  579. ret = out_fence_fd;
  580. goto out_post_unlock;
  581. }
  582. }
  583. submit = submit_create(dev, gpu, queue, args->nr_bos, args->nr_cmds);
  584. if (IS_ERR(submit)) {
  585. ret = PTR_ERR(submit);
  586. goto out_post_unlock;
  587. }
  588. trace_msm_gpu_submit(pid_nr(submit->pid), ring->id, submit->ident,
  589. args->nr_bos, args->nr_cmds);
  590. ret = mutex_lock_interruptible(&queue->lock);
  591. if (ret)
  592. goto out_post_unlock;
  593. if (args->flags & MSM_SUBMIT_SUDO)
  594. submit->in_rb = true;
  595. if (args->flags & MSM_SUBMIT_FENCE_FD_IN) {
  596. struct dma_fence *in_fence;
  597. in_fence = sync_file_get_fence(args->fence_fd);
  598. if (!in_fence) {
  599. ret = -EINVAL;
  600. goto out_unlock;
  601. }
  602. ret = drm_sched_job_add_dependency(&submit->base, in_fence);
  603. if (ret)
  604. goto out_unlock;
  605. }
  606. if (args->flags & MSM_SUBMIT_SYNCOBJ_IN) {
  607. syncobjs_to_reset = msm_parse_deps(submit, file,
  608. args->in_syncobjs,
  609. args->nr_in_syncobjs,
  610. args->syncobj_stride);
  611. if (IS_ERR(syncobjs_to_reset)) {
  612. ret = PTR_ERR(syncobjs_to_reset);
  613. goto out_unlock;
  614. }
  615. }
  616. if (args->flags & MSM_SUBMIT_SYNCOBJ_OUT) {
  617. post_deps = msm_parse_post_deps(dev, file,
  618. args->out_syncobjs,
  619. args->nr_out_syncobjs,
  620. args->syncobj_stride);
  621. if (IS_ERR(post_deps)) {
  622. ret = PTR_ERR(post_deps);
  623. goto out_unlock;
  624. }
  625. }
  626. ret = submit_lookup_objects(submit, args, file);
  627. if (ret)
  628. goto out;
  629. ret = submit_lookup_cmds(submit, args, file);
  630. if (ret)
  631. goto out;
  632. /* copy_*_user while holding a ww ticket upsets lockdep */
  633. ret = submit_lock_objects(submit);
  634. if (ret)
  635. goto out;
  636. if (!(args->flags & MSM_SUBMIT_NO_IMPLICIT)) {
  637. ret = submit_fence_sync(submit);
  638. if (ret)
  639. goto out;
  640. }
  641. ret = submit_pin_objects(submit);
  642. if (ret)
  643. goto out;
  644. for (i = 0; i < args->nr_cmds; i++) {
  645. struct drm_gem_object *obj;
  646. uint64_t iova;
  647. ret = submit_bo(submit, submit->cmd[i].idx, &obj, &iova);
  648. if (ret)
  649. goto out;
  650. if (!submit->cmd[i].size ||
  651. (size_add(submit->cmd[i].size, submit->cmd[i].offset) > obj->size / 4)) {
  652. SUBMIT_ERROR(submit, "invalid cmdstream size: %u\n", submit->cmd[i].size * 4);
  653. ret = -EINVAL;
  654. goto out;
  655. }
  656. submit->cmd[i].iova = iova + (submit->cmd[i].offset * 4);
  657. if (likely(!submit->cmd[i].nr_relocs))
  658. continue;
  659. if (!gpu->allow_relocs) {
  660. SUBMIT_ERROR(submit, "relocs not allowed\n");
  661. ret = -EINVAL;
  662. goto out;
  663. }
  664. ret = submit_reloc(submit, obj, submit->cmd[i].offset * 4,
  665. submit->cmd[i].nr_relocs, submit->cmd[i].relocs);
  666. if (ret)
  667. goto out;
  668. }
  669. submit->nr_cmds = i;
  670. idr_preload(GFP_KERNEL);
  671. spin_lock(&queue->idr_lock);
  672. /*
  673. * If using userspace provided seqno fence, validate that the id
  674. * is available before arming sched job. Since access to fence_idr
  675. * is serialized on the queue lock, the slot should be still avail
  676. * after the job is armed
  677. */
  678. if ((args->flags & MSM_SUBMIT_FENCE_SN_IN) &&
  679. (!args->fence || idr_find(&queue->fence_idr, args->fence))) {
  680. spin_unlock(&queue->idr_lock);
  681. idr_preload_end();
  682. ret = -EINVAL;
  683. goto out;
  684. }
  685. drm_sched_job_arm(&submit->base);
  686. submit->user_fence = dma_fence_get(&submit->base.s_fence->finished);
  687. if (args->flags & MSM_SUBMIT_FENCE_SN_IN) {
  688. /*
  689. * Userspace has assigned the seqno fence that it wants
  690. * us to use. It is an error to pick a fence sequence
  691. * number that is not available.
  692. */
  693. submit->fence_id = args->fence;
  694. ret = idr_alloc_u32(&queue->fence_idr, submit->user_fence,
  695. &submit->fence_id, submit->fence_id,
  696. GFP_NOWAIT);
  697. /*
  698. * We've already validated that the fence_id slot is valid,
  699. * so if idr_alloc_u32 failed, it is a kernel bug
  700. */
  701. WARN_ON(ret);
  702. } else {
  703. /*
  704. * Allocate an id which can be used by WAIT_FENCE ioctl to map
  705. * back to the underlying fence.
  706. */
  707. submit->fence_id = idr_alloc_cyclic(&queue->fence_idr,
  708. submit->user_fence, 1,
  709. INT_MAX, GFP_NOWAIT);
  710. }
  711. spin_unlock(&queue->idr_lock);
  712. idr_preload_end();
  713. if (submit->fence_id < 0) {
  714. ret = submit->fence_id;
  715. submit->fence_id = 0;
  716. }
  717. if (ret == 0 && args->flags & MSM_SUBMIT_FENCE_FD_OUT) {
  718. sync_file = sync_file_create(submit->user_fence);
  719. if (!sync_file)
  720. ret = -ENOMEM;
  721. }
  722. if (ret)
  723. goto out;
  724. submit_attach_object_fences(submit);
  725. /* The scheduler owns a ref now: */
  726. msm_gem_submit_get(submit);
  727. msm_rd_dump_submit(priv->rd, submit, NULL);
  728. drm_sched_entity_push_job(&submit->base);
  729. args->fence = submit->fence_id;
  730. queue->last_fence = submit->fence_id;
  731. msm_reset_syncobjs(syncobjs_to_reset, args->nr_in_syncobjs);
  732. msm_process_post_deps(post_deps, args->nr_out_syncobjs,
  733. submit->user_fence);
  734. out:
  735. submit_cleanup(submit, !!ret);
  736. out_unlock:
  737. mutex_unlock(&queue->lock);
  738. out_post_unlock:
  739. if (ret) {
  740. if (out_fence_fd >= 0)
  741. put_unused_fd(out_fence_fd);
  742. if (sync_file)
  743. fput(sync_file->file);
  744. } else if (sync_file) {
  745. fd_install(out_fence_fd, sync_file->file);
  746. args->fence_fd = out_fence_fd;
  747. }
  748. if (!IS_ERR_OR_NULL(submit)) {
  749. msm_gem_submit_put(submit);
  750. } else {
  751. /*
  752. * If the submit hasn't yet taken ownership of the queue
  753. * then we need to drop the reference ourself:
  754. */
  755. msm_submitqueue_put(queue);
  756. }
  757. if (!IS_ERR_OR_NULL(post_deps)) {
  758. for (i = 0; i < args->nr_out_syncobjs; ++i) {
  759. kfree(post_deps[i].chain);
  760. drm_syncobj_put(post_deps[i].syncobj);
  761. }
  762. kfree(post_deps);
  763. }
  764. if (!IS_ERR_OR_NULL(syncobjs_to_reset)) {
  765. for (i = 0; i < args->nr_in_syncobjs; ++i) {
  766. if (syncobjs_to_reset[i])
  767. drm_syncobj_put(syncobjs_to_reset[i]);
  768. }
  769. kfree(syncobjs_to_reset);
  770. }
  771. return ret;
  772. }