sde_vm_common.c 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (c) 2020, The Linux Foundation. All rights reserved.
  4. */
  5. #include <linux/list_sort.h>
  6. #include "linux/sde_rsc.h"
  7. #include "dsi/dsi_display.h"
  8. #include "dp/dp_display.h"
  9. #include "sde_kms.h"
  10. #include "sde_vm_common.h"
  11. struct hh_notify_vmid_desc *sde_vm_populate_vmid(hh_vmid_t vmid)
  12. {
  13. struct hh_notify_vmid_desc *vmid_desc;
  14. vmid_desc = kzalloc(offsetof(struct hh_notify_vmid_desc,
  15. vmid_entries[1]), GFP_KERNEL);
  16. if (!vmid_desc)
  17. return ERR_PTR(ENOMEM);
  18. vmid_desc->n_vmid_entries = 1;
  19. vmid_desc->vmid_entries[0].vmid = vmid;
  20. return vmid_desc;
  21. }
  22. struct hh_acl_desc *sde_vm_populate_acl(enum hh_vm_names vm_name)
  23. {
  24. struct hh_acl_desc *acl_desc;
  25. hh_vmid_t vmid;
  26. hh_rm_get_vmid(vm_name, &vmid);
  27. acl_desc = kzalloc(offsetof(struct hh_acl_desc, acl_entries[1]),
  28. GFP_KERNEL);
  29. if (!acl_desc)
  30. return ERR_PTR(ENOMEM);
  31. acl_desc->n_acl_entries = 1;
  32. acl_desc->acl_entries[0].vmid = vmid;
  33. acl_desc->acl_entries[0].perms = HH_RM_ACL_R | HH_RM_ACL_W;
  34. return acl_desc;
  35. }
  36. int __mem_sort_cmp(void *priv, struct list_head *a, struct list_head *b)
  37. {
  38. struct msm_io_mem_entry *left =
  39. container_of(a, struct msm_io_mem_entry, list);
  40. struct msm_io_mem_entry *right =
  41. container_of(b, struct msm_io_mem_entry, list);
  42. return (left->base - right->base);
  43. }
  44. bool __merge_on_overlap(struct msm_io_mem_entry *res,
  45. const struct msm_io_mem_entry *left,
  46. const struct msm_io_mem_entry *right)
  47. {
  48. phys_addr_t l_s = left->base;
  49. phys_addr_t l_e = left->base + left->size;
  50. phys_addr_t r_s = right->base;
  51. phys_addr_t r_e = right->base + right->size;
  52. memset(res, 0, sizeof(*res));
  53. if (r_s <= l_e) {
  54. res->base = min(l_s, r_s);
  55. res->size = max(l_e, r_e) - res->base;
  56. return true;
  57. }
  58. return false;
  59. }
  60. void _sde_vm_sort_and_align(struct list_head *mem)
  61. {
  62. struct msm_io_mem_entry *entry, *tmp, *prev = NULL;
  63. struct msm_io_mem_entry merged_entry;
  64. list_for_each_entry(entry, mem, list) {
  65. entry->base = ALIGN_DOWN(entry->base, PAGE_SIZE);
  66. entry->size = ALIGN(entry->size, PAGE_SIZE);
  67. }
  68. list_sort(NULL, mem, __mem_sort_cmp);
  69. list_for_each_entry_safe(entry, tmp, mem, list) {
  70. if (prev && __merge_on_overlap(&merged_entry, prev, entry)) {
  71. prev->base = merged_entry.base;
  72. prev->size = merged_entry.size;
  73. list_del(&entry->list);
  74. entry = prev;
  75. }
  76. prev = entry;
  77. }
  78. list_for_each_entry(entry, mem, list)
  79. SDE_DEBUG("base: 0x%x - size: 0x%x\n",
  80. entry->base, entry->size);
  81. }
  82. struct hh_sgl_desc *sde_vm_populate_sgl(struct msm_io_res *io_res)
  83. {
  84. struct hh_sgl_desc *sgl_desc;
  85. struct msm_io_mem_entry *mem;
  86. u32 i = 0, num_mem_entry = 0;
  87. _sde_vm_sort_and_align(&io_res->mem);
  88. list_for_each_entry(mem, &io_res->mem, list)
  89. num_mem_entry++;
  90. sgl_desc = kzalloc(offsetof(struct hh_sgl_desc,
  91. sgl_entries[num_mem_entry]), GFP_KERNEL);
  92. if (!sgl_desc)
  93. return ERR_PTR(ENOMEM);
  94. sgl_desc->n_sgl_entries = num_mem_entry;
  95. list_for_each_entry(mem, &io_res->mem, list) {
  96. sgl_desc->sgl_entries[i].ipa_base = mem->base;
  97. sgl_desc->sgl_entries[i].size = mem->size;
  98. i++;
  99. }
  100. msm_dss_clean_io_mem(&io_res->mem);
  101. return sgl_desc;
  102. }
  103. struct sde_vm_irq_desc *sde_vm_populate_irq(struct msm_io_res *io_res)
  104. {
  105. struct msm_io_irq_entry *irq;
  106. u32 i = 0, num_irq = 0;
  107. struct sde_vm_irq_desc *irq_desc;
  108. list_for_each_entry(irq, &io_res->irq, list)
  109. num_irq++;
  110. irq_desc = kzalloc(sizeof(*irq_desc), GFP_KERNEL);
  111. if (!irq_desc)
  112. return ERR_PTR(ENOMEM);
  113. irq_desc->irq_entries = kcalloc(num_irq,
  114. sizeof(struct sde_vm_irq_entry),
  115. GFP_KERNEL);
  116. if (!irq_desc->irq_entries) {
  117. sde_vm_free_irq(irq_desc);
  118. return ERR_PTR(ENOMEM);
  119. }
  120. list_for_each_entry(irq, &io_res->irq, list) {
  121. struct sde_vm_irq_entry *entry = &irq_desc->irq_entries[i];
  122. entry->irq = irq->irq_num;
  123. entry->label = irq->label;
  124. i++;
  125. }
  126. irq_desc->n_irq = num_irq;
  127. msm_dss_clean_io_irq(&io_res->irq);
  128. return irq_desc;
  129. }
  130. void sde_vm_free_irq(struct sde_vm_irq_desc *irq_desc)
  131. {
  132. if (irq_desc && irq_desc->irq_entries)
  133. kfree(irq_desc->irq_entries);
  134. kfree(irq_desc);
  135. }
  136. int sde_vm_get_resources(struct sde_kms *sde_kms, struct msm_io_res *io_res)
  137. {
  138. struct msm_drm_private *priv = sde_kms->dev->dev_private;
  139. struct msm_vm_client_entry *entry;
  140. int rc = 0;
  141. rc = sde_kms_get_io_resources(sde_kms, io_res);
  142. if (rc)
  143. goto fail_get_res;
  144. list_for_each_entry(entry, &priv->vm_client_list, list) {
  145. if (!entry->ops.vm_get_io_resources)
  146. continue;
  147. rc = entry->ops.vm_get_io_resources(io_res, entry->data);
  148. if (rc) {
  149. SDE_ERROR("get_io_resources failed for device: %d\n",
  150. entry->dev->id);
  151. goto fail_get_res;
  152. }
  153. }
  154. return rc;
  155. fail_get_res:
  156. msm_dss_clean_io_mem(&io_res->mem);
  157. msm_dss_clean_io_irq(&io_res->irq);
  158. return rc;
  159. }
  160. void sde_vm_free_resources(struct msm_io_res *io_res)
  161. {
  162. msm_dss_clean_io_mem(&io_res->mem);
  163. msm_dss_clean_io_irq(&io_res->irq);
  164. }