lima_ctx.c 2.0 KB

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