pvr_context.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497
  1. // SPDX-License-Identifier: GPL-2.0-only OR MIT
  2. /* Copyright (c) 2023 Imagination Technologies Ltd. */
  3. #include "pvr_cccb.h"
  4. #include "pvr_context.h"
  5. #include "pvr_device.h"
  6. #include "pvr_drv.h"
  7. #include "pvr_gem.h"
  8. #include "pvr_job.h"
  9. #include "pvr_power.h"
  10. #include "pvr_rogue_fwif.h"
  11. #include "pvr_rogue_fwif_common.h"
  12. #include "pvr_rogue_fwif_resetframework.h"
  13. #include "pvr_stream.h"
  14. #include "pvr_stream_defs.h"
  15. #include "pvr_vm.h"
  16. #include <drm/drm_auth.h>
  17. #include <drm/drm_managed.h>
  18. #include <linux/bug.h>
  19. #include <linux/errno.h>
  20. #include <linux/kernel.h>
  21. #include <linux/list.h>
  22. #include <linux/sched.h>
  23. #include <linux/slab.h>
  24. #include <linux/spinlock.h>
  25. #include <linux/string.h>
  26. #include <linux/types.h>
  27. #include <linux/xarray.h>
  28. static int
  29. remap_priority(struct pvr_file *pvr_file, s32 uapi_priority,
  30. enum pvr_context_priority *priority_out)
  31. {
  32. switch (uapi_priority) {
  33. case DRM_PVR_CTX_PRIORITY_LOW:
  34. *priority_out = PVR_CTX_PRIORITY_LOW;
  35. break;
  36. case DRM_PVR_CTX_PRIORITY_NORMAL:
  37. *priority_out = PVR_CTX_PRIORITY_MEDIUM;
  38. break;
  39. case DRM_PVR_CTX_PRIORITY_HIGH:
  40. if (!capable(CAP_SYS_NICE) && !drm_is_current_master(from_pvr_file(pvr_file)))
  41. return -EACCES;
  42. *priority_out = PVR_CTX_PRIORITY_HIGH;
  43. break;
  44. default:
  45. return -EINVAL;
  46. }
  47. return 0;
  48. }
  49. static int get_fw_obj_size(enum drm_pvr_ctx_type type)
  50. {
  51. switch (type) {
  52. case DRM_PVR_CTX_TYPE_RENDER:
  53. return sizeof(struct rogue_fwif_fwrendercontext);
  54. case DRM_PVR_CTX_TYPE_COMPUTE:
  55. return sizeof(struct rogue_fwif_fwcomputecontext);
  56. case DRM_PVR_CTX_TYPE_TRANSFER_FRAG:
  57. return sizeof(struct rogue_fwif_fwtransfercontext);
  58. }
  59. return -EINVAL;
  60. }
  61. static int
  62. process_static_context_state(struct pvr_device *pvr_dev, const struct pvr_stream_cmd_defs *cmd_defs,
  63. u64 stream_user_ptr, u32 stream_size, void *dest)
  64. {
  65. void *stream;
  66. int err;
  67. stream = kzalloc(stream_size, GFP_KERNEL);
  68. if (!stream)
  69. return -ENOMEM;
  70. if (copy_from_user(stream, u64_to_user_ptr(stream_user_ptr), stream_size)) {
  71. err = -EFAULT;
  72. goto err_free;
  73. }
  74. err = pvr_stream_process(pvr_dev, cmd_defs, stream, stream_size, dest);
  75. if (err)
  76. goto err_free;
  77. kfree(stream);
  78. return 0;
  79. err_free:
  80. kfree(stream);
  81. return err;
  82. }
  83. static int init_render_fw_objs(struct pvr_context *ctx,
  84. struct drm_pvr_ioctl_create_context_args *args,
  85. void *fw_ctx_map)
  86. {
  87. struct rogue_fwif_static_rendercontext_state *static_rendercontext_state;
  88. struct rogue_fwif_fwrendercontext *fw_render_context = fw_ctx_map;
  89. if (!args->static_context_state_len)
  90. return -EINVAL;
  91. static_rendercontext_state = &fw_render_context->static_render_context_state;
  92. /* Copy static render context state from userspace. */
  93. return process_static_context_state(ctx->pvr_dev,
  94. &pvr_static_render_context_state_stream,
  95. args->static_context_state,
  96. args->static_context_state_len,
  97. &static_rendercontext_state->ctxswitch_regs[0]);
  98. }
  99. static int init_compute_fw_objs(struct pvr_context *ctx,
  100. struct drm_pvr_ioctl_create_context_args *args,
  101. void *fw_ctx_map)
  102. {
  103. struct rogue_fwif_fwcomputecontext *fw_compute_context = fw_ctx_map;
  104. struct rogue_fwif_cdm_registers_cswitch *ctxswitch_regs;
  105. if (!args->static_context_state_len)
  106. return -EINVAL;
  107. ctxswitch_regs = &fw_compute_context->static_compute_context_state.ctxswitch_regs;
  108. /* Copy static render context state from userspace. */
  109. return process_static_context_state(ctx->pvr_dev,
  110. &pvr_static_compute_context_state_stream,
  111. args->static_context_state,
  112. args->static_context_state_len,
  113. ctxswitch_regs);
  114. }
  115. static int init_transfer_fw_objs(struct pvr_context *ctx,
  116. struct drm_pvr_ioctl_create_context_args *args,
  117. void *fw_ctx_map)
  118. {
  119. if (args->static_context_state_len)
  120. return -EINVAL;
  121. return 0;
  122. }
  123. static int init_fw_objs(struct pvr_context *ctx,
  124. struct drm_pvr_ioctl_create_context_args *args,
  125. void *fw_ctx_map)
  126. {
  127. switch (ctx->type) {
  128. case DRM_PVR_CTX_TYPE_RENDER:
  129. return init_render_fw_objs(ctx, args, fw_ctx_map);
  130. case DRM_PVR_CTX_TYPE_COMPUTE:
  131. return init_compute_fw_objs(ctx, args, fw_ctx_map);
  132. case DRM_PVR_CTX_TYPE_TRANSFER_FRAG:
  133. return init_transfer_fw_objs(ctx, args, fw_ctx_map);
  134. }
  135. return -EINVAL;
  136. }
  137. static void
  138. ctx_fw_data_init(void *cpu_ptr, void *priv)
  139. {
  140. struct pvr_context *ctx = priv;
  141. memcpy(cpu_ptr, ctx->data, ctx->data_size);
  142. }
  143. /**
  144. * pvr_context_destroy_queues() - Destroy all queues attached to a context.
  145. * @ctx: Context to destroy queues on.
  146. *
  147. * Should be called when the last reference to a context object is dropped.
  148. * It releases all resources attached to the queues bound to this context.
  149. */
  150. static void pvr_context_destroy_queues(struct pvr_context *ctx)
  151. {
  152. switch (ctx->type) {
  153. case DRM_PVR_CTX_TYPE_RENDER:
  154. pvr_queue_destroy(ctx->queues.fragment);
  155. pvr_queue_destroy(ctx->queues.geometry);
  156. break;
  157. case DRM_PVR_CTX_TYPE_COMPUTE:
  158. pvr_queue_destroy(ctx->queues.compute);
  159. break;
  160. case DRM_PVR_CTX_TYPE_TRANSFER_FRAG:
  161. pvr_queue_destroy(ctx->queues.transfer);
  162. break;
  163. }
  164. }
  165. /**
  166. * pvr_context_create_queues() - Create all queues attached to a context.
  167. * @ctx: Context to create queues on.
  168. * @args: Context creation arguments passed by userspace.
  169. * @fw_ctx_map: CPU mapping of the FW context object.
  170. *
  171. * Return:
  172. * * 0 on success, or
  173. * * A negative error code otherwise.
  174. */
  175. static int pvr_context_create_queues(struct pvr_context *ctx,
  176. struct drm_pvr_ioctl_create_context_args *args,
  177. void *fw_ctx_map)
  178. {
  179. int err;
  180. switch (ctx->type) {
  181. case DRM_PVR_CTX_TYPE_RENDER:
  182. ctx->queues.geometry = pvr_queue_create(ctx, DRM_PVR_JOB_TYPE_GEOMETRY,
  183. args, fw_ctx_map);
  184. if (IS_ERR(ctx->queues.geometry)) {
  185. err = PTR_ERR(ctx->queues.geometry);
  186. ctx->queues.geometry = NULL;
  187. goto err_destroy_queues;
  188. }
  189. ctx->queues.fragment = pvr_queue_create(ctx, DRM_PVR_JOB_TYPE_FRAGMENT,
  190. args, fw_ctx_map);
  191. if (IS_ERR(ctx->queues.fragment)) {
  192. err = PTR_ERR(ctx->queues.fragment);
  193. ctx->queues.fragment = NULL;
  194. goto err_destroy_queues;
  195. }
  196. return 0;
  197. case DRM_PVR_CTX_TYPE_COMPUTE:
  198. ctx->queues.compute = pvr_queue_create(ctx, DRM_PVR_JOB_TYPE_COMPUTE,
  199. args, fw_ctx_map);
  200. if (IS_ERR(ctx->queues.compute)) {
  201. err = PTR_ERR(ctx->queues.compute);
  202. ctx->queues.compute = NULL;
  203. goto err_destroy_queues;
  204. }
  205. return 0;
  206. case DRM_PVR_CTX_TYPE_TRANSFER_FRAG:
  207. ctx->queues.transfer = pvr_queue_create(ctx, DRM_PVR_JOB_TYPE_TRANSFER_FRAG,
  208. args, fw_ctx_map);
  209. if (IS_ERR(ctx->queues.transfer)) {
  210. err = PTR_ERR(ctx->queues.transfer);
  211. ctx->queues.transfer = NULL;
  212. goto err_destroy_queues;
  213. }
  214. return 0;
  215. }
  216. return -EINVAL;
  217. err_destroy_queues:
  218. pvr_context_destroy_queues(ctx);
  219. return err;
  220. }
  221. /**
  222. * pvr_context_kill_queues() - Kill queues attached to context.
  223. * @ctx: Context to kill queues on.
  224. *
  225. * Killing the queues implies making them unusable for future jobs, while still
  226. * letting the currently submitted jobs a chance to finish. Queue resources will
  227. * stay around until pvr_context_destroy_queues() is called.
  228. */
  229. static void pvr_context_kill_queues(struct pvr_context *ctx)
  230. {
  231. switch (ctx->type) {
  232. case DRM_PVR_CTX_TYPE_RENDER:
  233. pvr_queue_kill(ctx->queues.fragment);
  234. pvr_queue_kill(ctx->queues.geometry);
  235. break;
  236. case DRM_PVR_CTX_TYPE_COMPUTE:
  237. pvr_queue_kill(ctx->queues.compute);
  238. break;
  239. case DRM_PVR_CTX_TYPE_TRANSFER_FRAG:
  240. pvr_queue_kill(ctx->queues.transfer);
  241. break;
  242. }
  243. }
  244. /**
  245. * pvr_context_create() - Create a context.
  246. * @pvr_file: File to attach the created context to.
  247. * @args: Context creation arguments.
  248. *
  249. * Return:
  250. * * 0 on success, or
  251. * * A negative error code on failure.
  252. */
  253. int pvr_context_create(struct pvr_file *pvr_file, struct drm_pvr_ioctl_create_context_args *args)
  254. {
  255. struct pvr_device *pvr_dev = pvr_file->pvr_dev;
  256. struct pvr_context *ctx;
  257. int ctx_size;
  258. int err;
  259. /* Context creation flags are currently unused and must be zero. */
  260. if (args->flags)
  261. return -EINVAL;
  262. ctx_size = get_fw_obj_size(args->type);
  263. if (ctx_size < 0)
  264. return ctx_size;
  265. ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
  266. if (!ctx)
  267. return -ENOMEM;
  268. ctx->data_size = ctx_size;
  269. ctx->type = args->type;
  270. ctx->flags = args->flags;
  271. ctx->pvr_dev = pvr_dev;
  272. kref_init(&ctx->ref_count);
  273. err = remap_priority(pvr_file, args->priority, &ctx->priority);
  274. if (err)
  275. goto err_free_ctx;
  276. ctx->vm_ctx = pvr_vm_context_lookup(pvr_file, args->vm_context_handle);
  277. if (IS_ERR(ctx->vm_ctx)) {
  278. err = PTR_ERR(ctx->vm_ctx);
  279. goto err_free_ctx;
  280. }
  281. ctx->data = kzalloc(ctx_size, GFP_KERNEL);
  282. if (!ctx->data) {
  283. err = -ENOMEM;
  284. goto err_put_vm;
  285. }
  286. err = pvr_context_create_queues(ctx, args, ctx->data);
  287. if (err)
  288. goto err_free_ctx_data;
  289. err = init_fw_objs(ctx, args, ctx->data);
  290. if (err)
  291. goto err_destroy_queues;
  292. err = pvr_fw_object_create(pvr_dev, ctx_size, PVR_BO_FW_FLAGS_DEVICE_UNCACHED,
  293. ctx_fw_data_init, ctx, &ctx->fw_obj);
  294. if (err)
  295. goto err_free_ctx_data;
  296. err = xa_alloc(&pvr_dev->ctx_ids, &ctx->ctx_id, ctx, xa_limit_32b, GFP_KERNEL);
  297. if (err)
  298. goto err_destroy_fw_obj;
  299. err = xa_alloc(&pvr_file->ctx_handles, &args->handle, ctx, xa_limit_32b, GFP_KERNEL);
  300. if (err) {
  301. /*
  302. * It's possible that another thread could have taken a reference on the context at
  303. * this point as it is in the ctx_ids xarray. Therefore instead of directly
  304. * destroying the context, drop a reference instead.
  305. */
  306. pvr_context_put(ctx);
  307. return err;
  308. }
  309. spin_lock(&pvr_dev->ctx_list_lock);
  310. list_add_tail(&ctx->file_link, &pvr_file->contexts);
  311. spin_unlock(&pvr_dev->ctx_list_lock);
  312. return 0;
  313. err_destroy_fw_obj:
  314. pvr_fw_object_destroy(ctx->fw_obj);
  315. err_destroy_queues:
  316. pvr_context_destroy_queues(ctx);
  317. err_free_ctx_data:
  318. kfree(ctx->data);
  319. err_put_vm:
  320. pvr_vm_context_put(ctx->vm_ctx);
  321. err_free_ctx:
  322. kfree(ctx);
  323. return err;
  324. }
  325. static void
  326. pvr_context_release(struct kref *ref_count)
  327. {
  328. struct pvr_context *ctx =
  329. container_of(ref_count, struct pvr_context, ref_count);
  330. struct pvr_device *pvr_dev = ctx->pvr_dev;
  331. WARN_ON(in_interrupt());
  332. spin_lock(&pvr_dev->ctx_list_lock);
  333. list_del(&ctx->file_link);
  334. spin_unlock(&pvr_dev->ctx_list_lock);
  335. xa_erase(&pvr_dev->ctx_ids, ctx->ctx_id);
  336. pvr_context_destroy_queues(ctx);
  337. pvr_fw_object_destroy(ctx->fw_obj);
  338. kfree(ctx->data);
  339. pvr_vm_context_put(ctx->vm_ctx);
  340. kfree(ctx);
  341. }
  342. /**
  343. * pvr_context_put() - Release reference on context
  344. * @ctx: Target context.
  345. */
  346. void
  347. pvr_context_put(struct pvr_context *ctx)
  348. {
  349. if (ctx)
  350. kref_put(&ctx->ref_count, pvr_context_release);
  351. }
  352. /**
  353. * pvr_context_destroy() - Destroy context
  354. * @pvr_file: Pointer to pvr_file structure.
  355. * @handle: Userspace context handle.
  356. *
  357. * Removes context from context list and drops initial reference. Context will
  358. * then be destroyed once all outstanding references are dropped.
  359. *
  360. * Return:
  361. * * 0 on success, or
  362. * * -%EINVAL if context not in context list.
  363. */
  364. int
  365. pvr_context_destroy(struct pvr_file *pvr_file, u32 handle)
  366. {
  367. struct pvr_context *ctx = xa_erase(&pvr_file->ctx_handles, handle);
  368. if (!ctx)
  369. return -EINVAL;
  370. /* Make sure nothing can be queued to the queues after that point. */
  371. pvr_context_kill_queues(ctx);
  372. /* Release the reference held by the handle set. */
  373. pvr_context_put(ctx);
  374. return 0;
  375. }
  376. /**
  377. * pvr_destroy_contexts_for_file: Destroy any contexts associated with the given file
  378. * @pvr_file: Pointer to pvr_file structure.
  379. *
  380. * Removes all contexts associated with @pvr_file from the device context list and drops initial
  381. * references. Contexts will then be destroyed once all outstanding references are dropped.
  382. */
  383. void pvr_destroy_contexts_for_file(struct pvr_file *pvr_file)
  384. {
  385. struct pvr_device *pvr_dev = pvr_file->pvr_dev;
  386. struct pvr_context *ctx;
  387. unsigned long handle;
  388. xa_for_each(&pvr_file->ctx_handles, handle, ctx)
  389. pvr_context_destroy(pvr_file, handle);
  390. spin_lock(&pvr_dev->ctx_list_lock);
  391. ctx = list_first_entry(&pvr_file->contexts, struct pvr_context, file_link);
  392. while (!list_entry_is_head(ctx, &pvr_file->contexts, file_link)) {
  393. list_del_init(&ctx->file_link);
  394. if (pvr_context_get_if_referenced(ctx)) {
  395. spin_unlock(&pvr_dev->ctx_list_lock);
  396. pvr_vm_unmap_all(ctx->vm_ctx);
  397. pvr_context_put(ctx);
  398. spin_lock(&pvr_dev->ctx_list_lock);
  399. }
  400. ctx = list_first_entry(&pvr_file->contexts, struct pvr_context, file_link);
  401. }
  402. spin_unlock(&pvr_dev->ctx_list_lock);
  403. }
  404. /**
  405. * pvr_context_device_init() - Device level initialization for queue related resources.
  406. * @pvr_dev: The device to initialize.
  407. */
  408. void pvr_context_device_init(struct pvr_device *pvr_dev)
  409. {
  410. xa_init_flags(&pvr_dev->ctx_ids, XA_FLAGS_ALLOC1);
  411. spin_lock_init(&pvr_dev->ctx_list_lock);
  412. }
  413. /**
  414. * pvr_context_device_fini() - Device level cleanup for queue related resources.
  415. * @pvr_dev: The device to cleanup.
  416. */
  417. void pvr_context_device_fini(struct pvr_device *pvr_dev)
  418. {
  419. WARN_ON(!xa_empty(&pvr_dev->ctx_ids));
  420. xa_destroy(&pvr_dev->ctx_ids);
  421. }