pvr_job.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793
  1. // SPDX-License-Identifier: GPL-2.0-only OR MIT
  2. /* Copyright (c) 2023 Imagination Technologies Ltd. */
  3. #include "pvr_context.h"
  4. #include "pvr_device.h"
  5. #include "pvr_drv.h"
  6. #include "pvr_gem.h"
  7. #include "pvr_hwrt.h"
  8. #include "pvr_job.h"
  9. #include "pvr_mmu.h"
  10. #include "pvr_power.h"
  11. #include "pvr_rogue_fwif.h"
  12. #include "pvr_rogue_fwif_client.h"
  13. #include "pvr_stream.h"
  14. #include "pvr_stream_defs.h"
  15. #include "pvr_sync.h"
  16. #include <drm/drm_exec.h>
  17. #include <drm/drm_gem.h>
  18. #include <linux/types.h>
  19. #include <uapi/drm/pvr_drm.h>
  20. static void pvr_job_release(struct kref *kref)
  21. {
  22. struct pvr_job *job = container_of(kref, struct pvr_job, ref_count);
  23. xa_erase(&job->pvr_dev->job_ids, job->id);
  24. pvr_hwrt_data_put(job->hwrt);
  25. pvr_context_put(job->ctx);
  26. WARN_ON(job->paired_job);
  27. pvr_queue_job_cleanup(job);
  28. pvr_job_release_pm_ref(job);
  29. kfree(job->cmd);
  30. kfree(job);
  31. }
  32. /**
  33. * pvr_job_put() - Release reference on job
  34. * @job: Target job.
  35. */
  36. void
  37. pvr_job_put(struct pvr_job *job)
  38. {
  39. if (job)
  40. kref_put(&job->ref_count, pvr_job_release);
  41. }
  42. /**
  43. * pvr_job_process_stream() - Build job FW structure from stream
  44. * @pvr_dev: Device pointer.
  45. * @cmd_defs: Stream definition.
  46. * @stream: Pointer to command stream.
  47. * @stream_size: Size of command stream, in bytes.
  48. * @job: Pointer to job.
  49. *
  50. * Caller is responsible for freeing the output structure.
  51. *
  52. * Returns:
  53. * * 0 on success,
  54. * * -%ENOMEM on out of memory, or
  55. * * -%EINVAL on malformed stream.
  56. */
  57. static int
  58. pvr_job_process_stream(struct pvr_device *pvr_dev, const struct pvr_stream_cmd_defs *cmd_defs,
  59. void *stream, u32 stream_size, struct pvr_job *job)
  60. {
  61. int err;
  62. job->cmd = kzalloc(cmd_defs->dest_size, GFP_KERNEL);
  63. if (!job->cmd)
  64. return -ENOMEM;
  65. job->cmd_len = cmd_defs->dest_size;
  66. err = pvr_stream_process(pvr_dev, cmd_defs, stream, stream_size, job->cmd);
  67. if (err)
  68. kfree(job->cmd);
  69. return err;
  70. }
  71. static int pvr_fw_cmd_init(struct pvr_device *pvr_dev, struct pvr_job *job,
  72. const struct pvr_stream_cmd_defs *stream_def,
  73. u64 stream_userptr, u32 stream_len)
  74. {
  75. void *stream;
  76. int err;
  77. stream = kzalloc(stream_len, GFP_KERNEL);
  78. if (!stream)
  79. return -ENOMEM;
  80. if (copy_from_user(stream, u64_to_user_ptr(stream_userptr), stream_len)) {
  81. err = -EFAULT;
  82. goto err_free_stream;
  83. }
  84. err = pvr_job_process_stream(pvr_dev, stream_def, stream, stream_len, job);
  85. err_free_stream:
  86. kfree(stream);
  87. return err;
  88. }
  89. static u32
  90. convert_geom_flags(u32 in_flags)
  91. {
  92. u32 out_flags = 0;
  93. if (in_flags & DRM_PVR_SUBMIT_JOB_GEOM_CMD_FIRST)
  94. out_flags |= ROGUE_GEOM_FLAGS_FIRSTKICK;
  95. if (in_flags & DRM_PVR_SUBMIT_JOB_GEOM_CMD_LAST)
  96. out_flags |= ROGUE_GEOM_FLAGS_LASTKICK;
  97. if (in_flags & DRM_PVR_SUBMIT_JOB_GEOM_CMD_SINGLE_CORE)
  98. out_flags |= ROGUE_GEOM_FLAGS_SINGLE_CORE;
  99. return out_flags;
  100. }
  101. static u32
  102. convert_frag_flags(u32 in_flags)
  103. {
  104. u32 out_flags = 0;
  105. if (in_flags & DRM_PVR_SUBMIT_JOB_FRAG_CMD_SINGLE_CORE)
  106. out_flags |= ROGUE_FRAG_FLAGS_SINGLE_CORE;
  107. if (in_flags & DRM_PVR_SUBMIT_JOB_FRAG_CMD_DEPTHBUFFER)
  108. out_flags |= ROGUE_FRAG_FLAGS_DEPTHBUFFER;
  109. if (in_flags & DRM_PVR_SUBMIT_JOB_FRAG_CMD_STENCILBUFFER)
  110. out_flags |= ROGUE_FRAG_FLAGS_STENCILBUFFER;
  111. if (in_flags & DRM_PVR_SUBMIT_JOB_FRAG_CMD_PREVENT_CDM_OVERLAP)
  112. out_flags |= ROGUE_FRAG_FLAGS_PREVENT_CDM_OVERLAP;
  113. if (in_flags & DRM_PVR_SUBMIT_JOB_FRAG_CMD_SCRATCHBUFFER)
  114. out_flags |= ROGUE_FRAG_FLAGS_SCRATCHBUFFER;
  115. if (in_flags & DRM_PVR_SUBMIT_JOB_FRAG_CMD_GET_VIS_RESULTS)
  116. out_flags |= ROGUE_FRAG_FLAGS_GET_VIS_RESULTS;
  117. if (in_flags & DRM_PVR_SUBMIT_JOB_FRAG_CMD_DISABLE_PIXELMERGE)
  118. out_flags |= ROGUE_FRAG_FLAGS_DISABLE_PIXELMERGE;
  119. return out_flags;
  120. }
  121. static int
  122. pvr_geom_job_fw_cmd_init(struct pvr_job *job,
  123. struct drm_pvr_job *args)
  124. {
  125. struct rogue_fwif_cmd_geom *cmd;
  126. int err;
  127. if (args->flags & ~DRM_PVR_SUBMIT_JOB_GEOM_CMD_FLAGS_MASK)
  128. return -EINVAL;
  129. if (job->ctx->type != DRM_PVR_CTX_TYPE_RENDER)
  130. return -EINVAL;
  131. if (!job->hwrt)
  132. return -EINVAL;
  133. job->fw_ccb_cmd_type = ROGUE_FWIF_CCB_CMD_TYPE_GEOM;
  134. err = pvr_fw_cmd_init(job->pvr_dev, job, &pvr_cmd_geom_stream,
  135. args->cmd_stream, args->cmd_stream_len);
  136. if (err)
  137. return err;
  138. cmd = job->cmd;
  139. cmd->cmd_shared.cmn.frame_num = 0;
  140. cmd->flags = convert_geom_flags(args->flags);
  141. pvr_fw_object_get_fw_addr(job->hwrt->fw_obj, &cmd->cmd_shared.hwrt_data_fw_addr);
  142. return 0;
  143. }
  144. static int
  145. pvr_frag_job_fw_cmd_init(struct pvr_job *job,
  146. struct drm_pvr_job *args)
  147. {
  148. struct rogue_fwif_cmd_frag *cmd;
  149. int err;
  150. if (args->flags & ~DRM_PVR_SUBMIT_JOB_FRAG_CMD_FLAGS_MASK)
  151. return -EINVAL;
  152. if (job->ctx->type != DRM_PVR_CTX_TYPE_RENDER)
  153. return -EINVAL;
  154. if (!job->hwrt)
  155. return -EINVAL;
  156. job->fw_ccb_cmd_type = (args->flags & DRM_PVR_SUBMIT_JOB_FRAG_CMD_PARTIAL_RENDER) ?
  157. ROGUE_FWIF_CCB_CMD_TYPE_FRAG_PR :
  158. ROGUE_FWIF_CCB_CMD_TYPE_FRAG;
  159. err = pvr_fw_cmd_init(job->pvr_dev, job, &pvr_cmd_frag_stream,
  160. args->cmd_stream, args->cmd_stream_len);
  161. if (err)
  162. return err;
  163. cmd = job->cmd;
  164. cmd->cmd_shared.cmn.frame_num = 0;
  165. cmd->flags = convert_frag_flags(args->flags);
  166. pvr_fw_object_get_fw_addr(job->hwrt->fw_obj, &cmd->cmd_shared.hwrt_data_fw_addr);
  167. return 0;
  168. }
  169. static u32
  170. convert_compute_flags(u32 in_flags)
  171. {
  172. u32 out_flags = 0;
  173. if (in_flags & DRM_PVR_SUBMIT_JOB_COMPUTE_CMD_PREVENT_ALL_OVERLAP)
  174. out_flags |= ROGUE_COMPUTE_FLAG_PREVENT_ALL_OVERLAP;
  175. if (in_flags & DRM_PVR_SUBMIT_JOB_COMPUTE_CMD_SINGLE_CORE)
  176. out_flags |= ROGUE_COMPUTE_FLAG_SINGLE_CORE;
  177. return out_flags;
  178. }
  179. static int
  180. pvr_compute_job_fw_cmd_init(struct pvr_job *job,
  181. struct drm_pvr_job *args)
  182. {
  183. struct rogue_fwif_cmd_compute *cmd;
  184. int err;
  185. if (args->flags & ~DRM_PVR_SUBMIT_JOB_COMPUTE_CMD_FLAGS_MASK)
  186. return -EINVAL;
  187. if (job->ctx->type != DRM_PVR_CTX_TYPE_COMPUTE)
  188. return -EINVAL;
  189. job->fw_ccb_cmd_type = ROGUE_FWIF_CCB_CMD_TYPE_CDM;
  190. err = pvr_fw_cmd_init(job->pvr_dev, job, &pvr_cmd_compute_stream,
  191. args->cmd_stream, args->cmd_stream_len);
  192. if (err)
  193. return err;
  194. cmd = job->cmd;
  195. cmd->common.frame_num = 0;
  196. cmd->flags = convert_compute_flags(args->flags);
  197. return 0;
  198. }
  199. static u32
  200. convert_transfer_flags(u32 in_flags)
  201. {
  202. u32 out_flags = 0;
  203. if (in_flags & DRM_PVR_SUBMIT_JOB_TRANSFER_CMD_SINGLE_CORE)
  204. out_flags |= ROGUE_TRANSFER_FLAGS_SINGLE_CORE;
  205. return out_flags;
  206. }
  207. static int
  208. pvr_transfer_job_fw_cmd_init(struct pvr_job *job,
  209. struct drm_pvr_job *args)
  210. {
  211. struct rogue_fwif_cmd_transfer *cmd;
  212. int err;
  213. if (args->flags & ~DRM_PVR_SUBMIT_JOB_TRANSFER_CMD_FLAGS_MASK)
  214. return -EINVAL;
  215. if (job->ctx->type != DRM_PVR_CTX_TYPE_TRANSFER_FRAG)
  216. return -EINVAL;
  217. job->fw_ccb_cmd_type = ROGUE_FWIF_CCB_CMD_TYPE_TQ_3D;
  218. err = pvr_fw_cmd_init(job->pvr_dev, job, &pvr_cmd_transfer_stream,
  219. args->cmd_stream, args->cmd_stream_len);
  220. if (err)
  221. return err;
  222. cmd = job->cmd;
  223. cmd->common.frame_num = 0;
  224. cmd->flags = convert_transfer_flags(args->flags);
  225. return 0;
  226. }
  227. static int
  228. pvr_job_fw_cmd_init(struct pvr_job *job,
  229. struct drm_pvr_job *args)
  230. {
  231. switch (args->type) {
  232. case DRM_PVR_JOB_TYPE_GEOMETRY:
  233. return pvr_geom_job_fw_cmd_init(job, args);
  234. case DRM_PVR_JOB_TYPE_FRAGMENT:
  235. return pvr_frag_job_fw_cmd_init(job, args);
  236. case DRM_PVR_JOB_TYPE_COMPUTE:
  237. return pvr_compute_job_fw_cmd_init(job, args);
  238. case DRM_PVR_JOB_TYPE_TRANSFER_FRAG:
  239. return pvr_transfer_job_fw_cmd_init(job, args);
  240. default:
  241. return -EINVAL;
  242. }
  243. }
  244. /**
  245. * struct pvr_job_data - Helper container for pairing jobs with the
  246. * sync_ops supplied for them by the user.
  247. */
  248. struct pvr_job_data {
  249. /** @job: Pointer to the job. */
  250. struct pvr_job *job;
  251. /** @sync_ops: Pointer to the sync_ops associated with @job. */
  252. struct drm_pvr_sync_op *sync_ops;
  253. /** @sync_op_count: Number of members of @sync_ops. */
  254. u32 sync_op_count;
  255. };
  256. /**
  257. * prepare_job_syncs() - Prepare all sync objects for a single job.
  258. * @pvr_file: PowerVR file.
  259. * @job_data: Precreated job and sync_ops array.
  260. * @signal_array: xarray to receive signal sync objects.
  261. *
  262. * Returns:
  263. * * 0 on success, or
  264. * * Any error code returned by pvr_sync_signal_array_collect_ops(),
  265. * pvr_sync_add_deps_to_job(), drm_sched_job_add_resv_dependencies() or
  266. * pvr_sync_signal_array_update_fences().
  267. */
  268. static int
  269. prepare_job_syncs(struct pvr_file *pvr_file,
  270. struct pvr_job_data *job_data,
  271. struct xarray *signal_array)
  272. {
  273. struct dma_fence *done_fence;
  274. int err = pvr_sync_signal_array_collect_ops(signal_array,
  275. from_pvr_file(pvr_file),
  276. job_data->sync_op_count,
  277. job_data->sync_ops);
  278. if (err)
  279. return err;
  280. err = pvr_sync_add_deps_to_job(pvr_file, &job_data->job->base,
  281. job_data->sync_op_count,
  282. job_data->sync_ops, signal_array);
  283. if (err)
  284. return err;
  285. if (job_data->job->hwrt) {
  286. /* The geometry job writes the HWRT region headers, which are
  287. * then read by the fragment job.
  288. */
  289. struct drm_gem_object *obj =
  290. gem_from_pvr_gem(job_data->job->hwrt->fw_obj->gem);
  291. enum dma_resv_usage usage =
  292. dma_resv_usage_rw(job_data->job->type ==
  293. DRM_PVR_JOB_TYPE_GEOMETRY);
  294. dma_resv_lock(obj->resv, NULL);
  295. err = drm_sched_job_add_resv_dependencies(&job_data->job->base,
  296. obj->resv, usage);
  297. dma_resv_unlock(obj->resv);
  298. if (err)
  299. return err;
  300. }
  301. /* We need to arm the job to get the job done fence. */
  302. done_fence = pvr_queue_job_arm(job_data->job);
  303. err = pvr_sync_signal_array_update_fences(signal_array,
  304. job_data->sync_op_count,
  305. job_data->sync_ops,
  306. done_fence);
  307. return err;
  308. }
  309. /**
  310. * prepare_job_syncs_for_each() - Prepare all sync objects for an array of jobs.
  311. * @pvr_file: PowerVR file.
  312. * @job_data: Array of precreated jobs and their sync_ops.
  313. * @job_count: Number of jobs.
  314. * @signal_array: xarray to receive signal sync objects.
  315. *
  316. * Returns:
  317. * * 0 on success, or
  318. * * Any error code returned by pvr_vm_bind_job_prepare_syncs().
  319. */
  320. static int
  321. prepare_job_syncs_for_each(struct pvr_file *pvr_file,
  322. struct pvr_job_data *job_data,
  323. u32 *job_count,
  324. struct xarray *signal_array)
  325. {
  326. for (u32 i = 0; i < *job_count; i++) {
  327. int err = prepare_job_syncs(pvr_file, &job_data[i],
  328. signal_array);
  329. if (err) {
  330. *job_count = i;
  331. return err;
  332. }
  333. }
  334. return 0;
  335. }
  336. static struct pvr_job *
  337. create_job(struct pvr_device *pvr_dev,
  338. struct pvr_file *pvr_file,
  339. struct drm_pvr_job *args)
  340. {
  341. struct pvr_job *job = NULL;
  342. int err;
  343. if (!args->cmd_stream || !args->cmd_stream_len)
  344. return ERR_PTR(-EINVAL);
  345. if (args->type != DRM_PVR_JOB_TYPE_GEOMETRY &&
  346. args->type != DRM_PVR_JOB_TYPE_FRAGMENT &&
  347. (args->hwrt.set_handle || args->hwrt.data_index))
  348. return ERR_PTR(-EINVAL);
  349. job = kzalloc(sizeof(*job), GFP_KERNEL);
  350. if (!job)
  351. return ERR_PTR(-ENOMEM);
  352. kref_init(&job->ref_count);
  353. job->type = args->type;
  354. job->pvr_dev = pvr_dev;
  355. err = xa_alloc(&pvr_dev->job_ids, &job->id, job, xa_limit_32b, GFP_KERNEL);
  356. if (err)
  357. goto err_put_job;
  358. job->ctx = pvr_context_lookup(pvr_file, args->context_handle);
  359. if (!job->ctx) {
  360. err = -EINVAL;
  361. goto err_put_job;
  362. }
  363. if (args->hwrt.set_handle) {
  364. job->hwrt = pvr_hwrt_data_lookup(pvr_file, args->hwrt.set_handle,
  365. args->hwrt.data_index);
  366. if (!job->hwrt) {
  367. err = -EINVAL;
  368. goto err_put_job;
  369. }
  370. }
  371. err = pvr_job_fw_cmd_init(job, args);
  372. if (err)
  373. goto err_put_job;
  374. err = pvr_queue_job_init(job);
  375. if (err)
  376. goto err_put_job;
  377. return job;
  378. err_put_job:
  379. pvr_job_put(job);
  380. return ERR_PTR(err);
  381. }
  382. /**
  383. * pvr_job_data_fini() - Cleanup all allocs used to set up job submission.
  384. * @job_data: Job data array.
  385. * @job_count: Number of members of @job_data.
  386. */
  387. static void
  388. pvr_job_data_fini(struct pvr_job_data *job_data, u32 job_count)
  389. {
  390. for (u32 i = 0; i < job_count; i++) {
  391. pvr_job_put(job_data[i].job);
  392. kvfree(job_data[i].sync_ops);
  393. }
  394. }
  395. /**
  396. * pvr_job_data_init() - Init an array of created jobs, associating them with
  397. * the appropriate sync_ops args, which will be copied in.
  398. * @pvr_dev: Target PowerVR device.
  399. * @pvr_file: Pointer to PowerVR file structure.
  400. * @job_args: Job args array copied from user.
  401. * @job_count: Number of members of @job_args.
  402. * @job_data_out: Job data array.
  403. */
  404. static int pvr_job_data_init(struct pvr_device *pvr_dev,
  405. struct pvr_file *pvr_file,
  406. struct drm_pvr_job *job_args,
  407. u32 *job_count,
  408. struct pvr_job_data *job_data_out)
  409. {
  410. int err = 0, i = 0;
  411. for (; i < *job_count; i++) {
  412. job_data_out[i].job =
  413. create_job(pvr_dev, pvr_file, &job_args[i]);
  414. err = PTR_ERR_OR_ZERO(job_data_out[i].job);
  415. if (err) {
  416. *job_count = i;
  417. job_data_out[i].job = NULL;
  418. goto err_cleanup;
  419. }
  420. err = PVR_UOBJ_GET_ARRAY(job_data_out[i].sync_ops,
  421. &job_args[i].sync_ops);
  422. if (err) {
  423. *job_count = i;
  424. /* Ensure the job created above is also cleaned up. */
  425. i++;
  426. goto err_cleanup;
  427. }
  428. job_data_out[i].sync_op_count = job_args[i].sync_ops.count;
  429. }
  430. return 0;
  431. err_cleanup:
  432. pvr_job_data_fini(job_data_out, i);
  433. return err;
  434. }
  435. static void
  436. push_jobs(struct pvr_job_data *job_data, u32 job_count)
  437. {
  438. for (u32 i = 0; i < job_count; i++)
  439. pvr_queue_job_push(job_data[i].job);
  440. }
  441. static int
  442. prepare_fw_obj_resv(struct drm_exec *exec, struct pvr_fw_object *fw_obj)
  443. {
  444. return drm_exec_prepare_obj(exec, gem_from_pvr_gem(fw_obj->gem), 1);
  445. }
  446. static int
  447. jobs_lock_all_objs(struct drm_exec *exec, struct pvr_job_data *job_data,
  448. u32 job_count)
  449. {
  450. for (u32 i = 0; i < job_count; i++) {
  451. struct pvr_job *job = job_data[i].job;
  452. /* Grab a lock on a the context, to guard against
  453. * concurrent submission to the same queue.
  454. */
  455. int err = drm_exec_lock_obj(exec,
  456. gem_from_pvr_gem(job->ctx->fw_obj->gem));
  457. if (err)
  458. return err;
  459. if (job->hwrt) {
  460. err = prepare_fw_obj_resv(exec,
  461. job->hwrt->fw_obj);
  462. if (err)
  463. return err;
  464. }
  465. }
  466. return 0;
  467. }
  468. static int
  469. prepare_job_resvs_for_each(struct drm_exec *exec, struct pvr_job_data *job_data,
  470. u32 job_count)
  471. {
  472. drm_exec_until_all_locked(exec) {
  473. int err = jobs_lock_all_objs(exec, job_data, job_count);
  474. drm_exec_retry_on_contention(exec);
  475. if (err)
  476. return err;
  477. }
  478. return 0;
  479. }
  480. static void
  481. update_job_resvs(struct pvr_job *job)
  482. {
  483. if (job->hwrt) {
  484. enum dma_resv_usage usage = job->type == DRM_PVR_JOB_TYPE_GEOMETRY ?
  485. DMA_RESV_USAGE_WRITE : DMA_RESV_USAGE_READ;
  486. struct drm_gem_object *obj = gem_from_pvr_gem(job->hwrt->fw_obj->gem);
  487. dma_resv_add_fence(obj->resv, &job->base.s_fence->finished, usage);
  488. }
  489. }
  490. static void
  491. update_job_resvs_for_each(struct pvr_job_data *job_data, u32 job_count)
  492. {
  493. for (u32 i = 0; i < job_count; i++)
  494. update_job_resvs(job_data[i].job);
  495. }
  496. static bool can_combine_jobs(struct pvr_job *a, struct pvr_job *b)
  497. {
  498. struct pvr_job *geom_job = a, *frag_job = b;
  499. struct dma_fence *fence;
  500. unsigned long index;
  501. /* Geometry and fragment jobs can be combined if they are queued to the
  502. * same context and targeting the same HWRT.
  503. */
  504. if (a->type != DRM_PVR_JOB_TYPE_GEOMETRY ||
  505. b->type != DRM_PVR_JOB_TYPE_FRAGMENT ||
  506. a->ctx != b->ctx ||
  507. a->hwrt != b->hwrt)
  508. return false;
  509. xa_for_each(&frag_job->base.dependencies, index, fence) {
  510. /* We combine when we see an explicit geom -> frag dep. */
  511. if (&geom_job->base.s_fence->scheduled == fence)
  512. return true;
  513. }
  514. return false;
  515. }
  516. static struct dma_fence *
  517. get_last_queued_job_scheduled_fence(struct pvr_queue *queue,
  518. struct pvr_job_data *job_data,
  519. u32 cur_job_pos)
  520. {
  521. /* We iterate over the current job array in reverse order to grab the
  522. * last to-be-queued job targeting the same queue.
  523. */
  524. for (u32 i = cur_job_pos; i > 0; i--) {
  525. struct pvr_job *job = job_data[i - 1].job;
  526. if (job->ctx == queue->ctx && job->type == queue->type)
  527. return dma_fence_get(&job->base.s_fence->scheduled);
  528. }
  529. /* If we didn't find any, we just return the last queued job scheduled
  530. * fence attached to the queue.
  531. */
  532. return dma_fence_get(queue->last_queued_job_scheduled_fence);
  533. }
  534. static int
  535. pvr_jobs_link_geom_frag(struct pvr_job_data *job_data, u32 *job_count)
  536. {
  537. for (u32 i = 0; i < *job_count - 1; i++) {
  538. struct pvr_job *geom_job = job_data[i].job;
  539. struct pvr_job *frag_job = job_data[i + 1].job;
  540. struct pvr_queue *frag_queue;
  541. struct dma_fence *f;
  542. if (!can_combine_jobs(job_data[i].job, job_data[i + 1].job))
  543. continue;
  544. /* The fragment job will be submitted by the geometry queue. We
  545. * need to make sure it comes after all the other fragment jobs
  546. * queued before it.
  547. */
  548. frag_queue = pvr_context_get_queue_for_job(frag_job->ctx,
  549. frag_job->type);
  550. f = get_last_queued_job_scheduled_fence(frag_queue, job_data,
  551. i);
  552. if (f) {
  553. int err = drm_sched_job_add_dependency(&geom_job->base,
  554. f);
  555. if (err) {
  556. *job_count = i;
  557. return err;
  558. }
  559. }
  560. /* The KCCB slot will be reserved by the geometry job, so we can
  561. * drop the KCCB fence on the fragment job.
  562. */
  563. pvr_kccb_fence_put(frag_job->kccb_fence);
  564. frag_job->kccb_fence = NULL;
  565. geom_job->paired_job = frag_job;
  566. frag_job->paired_job = geom_job;
  567. /* The geometry job pvr_job structure is used when the fragment
  568. * job is being prepared by the GPU scheduler. Have the fragment
  569. * job hold a reference on the geometry job to prevent it being
  570. * freed until the fragment job has finished with it.
  571. */
  572. pvr_job_get(geom_job);
  573. /* Skip the fragment job we just paired to the geometry job. */
  574. i++;
  575. }
  576. return 0;
  577. }
  578. /**
  579. * pvr_submit_jobs() - Submit jobs to the GPU
  580. * @pvr_dev: Target PowerVR device.
  581. * @pvr_file: Pointer to PowerVR file structure.
  582. * @args: Ioctl args.
  583. *
  584. * This initial implementation is entirely synchronous; on return the GPU will
  585. * be idle. This will not be the case for future implementations.
  586. *
  587. * Returns:
  588. * * 0 on success,
  589. * * -%EFAULT if arguments can not be copied from user space, or
  590. * * -%EINVAL on invalid arguments, or
  591. * * Any other error.
  592. */
  593. int
  594. pvr_submit_jobs(struct pvr_device *pvr_dev, struct pvr_file *pvr_file,
  595. struct drm_pvr_ioctl_submit_jobs_args *args)
  596. {
  597. struct pvr_job_data *job_data = NULL;
  598. struct drm_pvr_job *job_args;
  599. struct xarray signal_array;
  600. u32 jobs_alloced = 0;
  601. struct drm_exec exec;
  602. int err;
  603. if (!args->jobs.count)
  604. return -EINVAL;
  605. err = PVR_UOBJ_GET_ARRAY(job_args, &args->jobs);
  606. if (err)
  607. return err;
  608. job_data = kvmalloc_array(args->jobs.count, sizeof(*job_data),
  609. GFP_KERNEL | __GFP_ZERO);
  610. if (!job_data) {
  611. err = -ENOMEM;
  612. goto out_free;
  613. }
  614. err = pvr_job_data_init(pvr_dev, pvr_file, job_args, &args->jobs.count,
  615. job_data);
  616. if (err)
  617. goto out_free;
  618. jobs_alloced = args->jobs.count;
  619. /*
  620. * Flush MMU if needed - this has been deferred until now to avoid
  621. * overuse of this expensive operation.
  622. */
  623. err = pvr_mmu_flush_exec(pvr_dev, false);
  624. if (err)
  625. goto out_job_data_cleanup;
  626. drm_exec_init(&exec, DRM_EXEC_INTERRUPTIBLE_WAIT | DRM_EXEC_IGNORE_DUPLICATES, 0);
  627. xa_init_flags(&signal_array, XA_FLAGS_ALLOC);
  628. err = prepare_job_syncs_for_each(pvr_file, job_data, &args->jobs.count,
  629. &signal_array);
  630. if (err)
  631. goto out_exec_fini;
  632. err = prepare_job_resvs_for_each(&exec, job_data, args->jobs.count);
  633. if (err)
  634. goto out_exec_fini;
  635. err = pvr_jobs_link_geom_frag(job_data, &args->jobs.count);
  636. if (err)
  637. goto out_exec_fini;
  638. /* Anything after that point must succeed because we start exposing job
  639. * finished fences to the outside world.
  640. */
  641. update_job_resvs_for_each(job_data, args->jobs.count);
  642. push_jobs(job_data, args->jobs.count);
  643. pvr_sync_signal_array_push_fences(&signal_array);
  644. err = 0;
  645. out_exec_fini:
  646. drm_exec_fini(&exec);
  647. pvr_sync_signal_array_cleanup(&signal_array);
  648. out_job_data_cleanup:
  649. pvr_job_data_fini(job_data, jobs_alloced);
  650. out_free:
  651. kvfree(job_data);
  652. kvfree(job_args);
  653. return err;
  654. }