qcom_dma_heap.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
  4. * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
  5. */
  6. #include <linux/module.h>
  7. #include <linux/of_platform.h>
  8. #include <linux/platform_device.h>
  9. #include <linux/err.h>
  10. #include <linux/qcom_dma_heap.h>
  11. #include <linux/qcom_tui_heap.h>
  12. #include "qcom_cma_heap.h"
  13. #include "qcom_dt_parser.h"
  14. #include "qcom_system_heap.h"
  15. #include "qcom_carveout_heap.h"
  16. #include "qcom_secure_system_heap.h"
  17. #include "qcom_dma_heap_priv.h"
  18. #include "qcom_system_movable_heap.h"
  19. /*
  20. * We cache the file ops used by DMA-BUFs so that a user with a struct file
  21. * pointer can determine if that file is for a DMA-BUF. We can't initialize
  22. * the pointer here at compile time as ERR_PTR() evaluates to a function.
  23. */
  24. #define FOPS_INIT_VAL ERR_PTR(-EINVAL)
  25. static const struct file_operations *dma_buf_cached_fops;
  26. #if defined(CONFIG_RBIN)
  27. int add_rbin_heap(struct platform_heap *heap_data);
  28. #endif
  29. static int qcom_dma_heap_probe(struct platform_device *pdev)
  30. {
  31. int ret = 0;
  32. int i;
  33. struct platform_data *heaps;
  34. qcom_system_heap_create("qcom,system", "system", false);
  35. #ifdef CONFIG_QCOM_DMABUF_HEAPS_SYSTEM_UNCACHED
  36. qcom_system_heap_create("qcom,system-uncached", NULL, true);
  37. #endif
  38. qcom_secure_system_heap_create("qcom,secure-pixel", NULL,
  39. QCOM_DMA_HEAP_FLAG_CP_PIXEL);
  40. qcom_secure_system_heap_create("qcom,secure-non-pixel", NULL,
  41. QCOM_DMA_HEAP_FLAG_CP_NON_PIXEL);
  42. qcom_sys_movable_heap_create();
  43. heaps = parse_heap_dt(pdev);
  44. if (IS_ERR_OR_NULL(heaps))
  45. return PTR_ERR(heaps);
  46. for (i = 0; i < heaps->nr; i++) {
  47. struct platform_heap *heap_data = &heaps->heaps[i];
  48. switch (heap_data->type) {
  49. case HEAP_TYPE_SECURE_CARVEOUT:
  50. ret = qcom_secure_carveout_heap_create(heap_data);
  51. break;
  52. case HEAP_TYPE_CARVEOUT:
  53. ret = qcom_carveout_heap_create(heap_data);
  54. break;
  55. case HEAP_TYPE_CMA:
  56. ret = qcom_add_cma_heap(heap_data);
  57. break;
  58. case HEAP_TYPE_TUI_CARVEOUT:
  59. ret = qcom_tui_carveout_heap_create(heap_data);
  60. break;
  61. #if defined(CONFIG_RBIN)
  62. case HEAP_TYPE_RBIN:
  63. ret = add_rbin_heap(heap_data);
  64. if (ret < 0)
  65. pr_err("%s: DMA-BUF Heap: Failed to create %s, error is %d\n",
  66. __func__, heap_data->name, ret);
  67. else if (!ret)
  68. pr_info("%s: DMA-BUF Heap: Created %s\n", __func__,
  69. heap_data->name);
  70. break;
  71. #endif
  72. default:
  73. pr_err("%s: Unknown heap type %u\n", __func__, heap_data->type);
  74. break;
  75. }
  76. if (ret)
  77. pr_err("%s: DMA-BUF Heap: Failed to create %s, error is %d\n",
  78. __func__, heap_data->name, ret);
  79. else
  80. pr_info("%s: DMA-BUF Heap: Created %s\n", __func__,
  81. heap_data->name);
  82. }
  83. free_pdata(heaps);
  84. dma_buf_cached_fops = FOPS_INIT_VAL;
  85. return ret;
  86. }
  87. void qcom_store_dma_buf_fops(struct file *file)
  88. {
  89. if (dma_buf_cached_fops == FOPS_INIT_VAL)
  90. dma_buf_cached_fops = file->f_op;
  91. }
  92. EXPORT_SYMBOL(qcom_store_dma_buf_fops);
  93. bool qcom_is_dma_buf_file(struct file *file)
  94. {
  95. return file->f_op == dma_buf_cached_fops;
  96. }
  97. EXPORT_SYMBOL(qcom_is_dma_buf_file);
  98. static int qcom_dma_heaps_freeze(struct device *dev)
  99. {
  100. int ret;
  101. ret = qcom_secure_carveout_heap_freeze();
  102. if (ret) {
  103. pr_err("Failed to freeze secure carveout heap: %d\n", ret);
  104. return ret;
  105. }
  106. ret = qcom_secure_system_heap_freeze();
  107. if (ret) {
  108. pr_err("Failed to freeze secure system heap: %d\n", ret);
  109. goto err;
  110. }
  111. return 0;
  112. err:
  113. ret = qcom_secure_carveout_heap_restore();
  114. if (ret) {
  115. pr_err("Failed to restore secure carveout heap: %d\n", ret);
  116. return ret;
  117. }
  118. return -EBUSY;
  119. }
  120. static int qcom_dma_heaps_restore(struct device *dev)
  121. {
  122. int ret;
  123. ret = qcom_secure_carveout_heap_restore();
  124. if (ret)
  125. pr_err("Failed to restore secure carveout heap: %d\n", ret);
  126. ret = qcom_secure_system_heap_restore();
  127. if (ret)
  128. pr_err("Failed to restore secure system heap: %d\n", ret);
  129. return ret;
  130. }
  131. static const struct dev_pm_ops qcom_dma_heaps_pm_ops = {
  132. .freeze_late = qcom_dma_heaps_freeze,
  133. .restore_early = qcom_dma_heaps_restore,
  134. };
  135. static const struct of_device_id qcom_dma_heap_match_table[] = {
  136. {.compatible = "qcom,dma-heaps"},
  137. {},
  138. };
  139. static struct platform_driver qcom_dma_heap_driver = {
  140. .probe = qcom_dma_heap_probe,
  141. .driver = {
  142. .name = "qcom-dma-heap",
  143. .of_match_table = qcom_dma_heap_match_table,
  144. .pm = &qcom_dma_heaps_pm_ops,
  145. },
  146. };
  147. static int __init init_heap_driver(void)
  148. {
  149. return platform_driver_register(&qcom_dma_heap_driver);
  150. }
  151. module_init(init_heap_driver);
  152. MODULE_LICENSE("GPL v2");