lima_ctx.c 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. // SPDX-License-Identifier: GPL-2.0 OR MIT
  2. /* Copyright 2018-2019 Qiang Yu <yuq825@gmail.com> */
  3. #include <linux/pid.h>
  4. #include <linux/slab.h>
  5. #include "lima_device.h"
  6. #include "lima_ctx.h"
  7. int lima_ctx_create(struct lima_device *dev, struct lima_ctx_mgr *mgr, u32 *id)
  8. {
  9. struct lima_ctx *ctx;
  10. int i, err;
  11. ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
  12. if (!ctx)
  13. return -ENOMEM;
  14. ctx->dev = dev;
  15. kref_init(&ctx->refcnt);
  16. for (i = 0; i < lima_pipe_num; i++) {
  17. err = lima_sched_context_init(dev->pipe + i, ctx->context + i);
  18. if (err)
  19. goto err_out0;
  20. }
  21. err = xa_alloc(&mgr->handles, id, ctx, xa_limit_32b, GFP_KERNEL);
  22. if (err < 0)
  23. goto err_out0;
  24. ctx->pid = task_pid_nr(current);
  25. get_task_comm(ctx->pname, current);
  26. return 0;
  27. err_out0:
  28. for (i--; i >= 0; i--)
  29. lima_sched_context_fini(dev->pipe + i, ctx->context + i);
  30. kfree(ctx);
  31. return err;
  32. }
  33. static void lima_ctx_do_release(struct kref *ref)
  34. {
  35. struct lima_ctx *ctx = container_of(ref, struct lima_ctx, refcnt);
  36. int i;
  37. for (i = 0; i < lima_pipe_num; i++)
  38. lima_sched_context_fini(ctx->dev->pipe + i, ctx->context + i);
  39. kfree(ctx);
  40. }
  41. int lima_ctx_free(struct lima_ctx_mgr *mgr, u32 id)
  42. {
  43. struct lima_ctx *ctx;
  44. int ret = 0;
  45. mutex_lock(&mgr->lock);
  46. ctx = xa_erase(&mgr->handles, id);
  47. if (ctx)
  48. kref_put(&ctx->refcnt, lima_ctx_do_release);
  49. else
  50. ret = -EINVAL;
  51. mutex_unlock(&mgr->lock);
  52. return ret;
  53. }
  54. struct lima_ctx *lima_ctx_get(struct lima_ctx_mgr *mgr, u32 id)
  55. {
  56. struct lima_ctx *ctx;
  57. mutex_lock(&mgr->lock);
  58. ctx = xa_load(&mgr->handles, id);
  59. if (ctx)
  60. kref_get(&ctx->refcnt);
  61. mutex_unlock(&mgr->lock);
  62. return ctx;
  63. }
  64. void lima_ctx_put(struct lima_ctx *ctx)
  65. {
  66. kref_put(&ctx->refcnt, lima_ctx_do_release);
  67. }
  68. void lima_ctx_mgr_init(struct lima_ctx_mgr *mgr)
  69. {
  70. mutex_init(&mgr->lock);
  71. xa_init_flags(&mgr->handles, XA_FLAGS_ALLOC);
  72. }
  73. void lima_ctx_mgr_fini(struct lima_ctx_mgr *mgr)
  74. {
  75. struct lima_ctx *ctx;
  76. unsigned long id;
  77. xa_for_each(&mgr->handles, id, ctx) {
  78. kref_put(&ctx->refcnt, lima_ctx_do_release);
  79. }
  80. xa_destroy(&mgr->handles);
  81. mutex_destroy(&mgr->lock);
  82. }