mem.c 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. /*
  2. * Copyright (c) 2006-2022, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2022-08-25 GuEe-GUI first version
  9. */
  10. #include <drivers/pci_endpoint.h>
  11. #define DBG_TAG "pci.ep.mem"
  12. #define DBG_LVL DBG_INFO
  13. #include <rtdbg.h>
  14. rt_err_t rt_pci_ep_mem_array_init(struct rt_pci_ep *ep,
  15. struct rt_pci_ep_mem *mems, rt_size_t mems_nr)
  16. {
  17. rt_size_t idx;
  18. rt_err_t err = RT_EOK;
  19. if (!ep || !mems)
  20. {
  21. return -RT_EINVAL;
  22. }
  23. rt_mutex_take(&ep->lock, RT_WAITING_FOREVER);
  24. ep->mems_nr = mems_nr;
  25. ep->mems = rt_calloc(mems_nr, sizeof(*ep->mems));
  26. if (!ep->mems)
  27. {
  28. return -RT_ENOMEM;
  29. }
  30. for (idx = 0; idx < mems_nr; ++idx)
  31. {
  32. struct rt_pci_ep_mem *mem = &ep->mems[idx];
  33. mem->cpu_addr = mems->cpu_addr;
  34. mem->size = mems->size;
  35. mem->page_size = mems->page_size;
  36. mem->bits = mems->size / mems->page_size;
  37. mem->map = rt_calloc(RT_BITMAP_LEN(mem->bits), sizeof(*mem->map));
  38. if (!mem->map)
  39. {
  40. err = -RT_ENOMEM;
  41. goto _out_lock;
  42. }
  43. }
  44. _out_lock:
  45. if (err)
  46. {
  47. while (idx --> 0)
  48. {
  49. rt_free(ep->mems[idx].map);
  50. }
  51. rt_free(ep->mems);
  52. ep->mems_nr = 0;
  53. ep->mems = RT_NULL;
  54. }
  55. rt_mutex_release(&ep->lock);
  56. return err;
  57. }
  58. rt_err_t rt_pci_ep_mem_init(struct rt_pci_ep *ep,
  59. rt_ubase_t cpu_addr, rt_size_t size, rt_size_t page_size)
  60. {
  61. struct rt_pci_ep_mem mem;
  62. if (!ep)
  63. {
  64. return -RT_EINVAL;
  65. }
  66. mem.cpu_addr = cpu_addr;
  67. mem.size = size;
  68. mem.page_size = page_size;
  69. return rt_pci_ep_mem_array_init(ep, &mem, 1);
  70. }
  71. static rt_ubase_t bitmap_region_alloc(struct rt_pci_ep_mem *mem, rt_size_t size)
  72. {
  73. rt_size_t bit, next_bit, end_bit, max_bits;
  74. size /= mem->page_size;
  75. max_bits = mem->bits - size;
  76. rt_bitmap_for_each_clear_bit(mem->map, bit, max_bits)
  77. {
  78. end_bit = bit + size;
  79. for (next_bit = bit + 1; next_bit < end_bit; ++next_bit)
  80. {
  81. if (rt_bitmap_test_bit(mem->map, next_bit))
  82. {
  83. bit = next_bit;
  84. goto _next;
  85. }
  86. }
  87. if (next_bit == end_bit)
  88. {
  89. while (next_bit --> bit)
  90. {
  91. rt_bitmap_set_bit(mem->map, next_bit);
  92. }
  93. return mem->cpu_addr + bit * mem->page_size;
  94. }
  95. _next:
  96. }
  97. return ~0ULL;
  98. }
  99. static void bitmap_region_free(struct rt_pci_ep_mem *mem,
  100. rt_ubase_t cpu_addr, rt_size_t size)
  101. {
  102. rt_size_t bit = (cpu_addr - mem->cpu_addr) / mem->page_size, end_bit;
  103. size /= mem->page_size;
  104. end_bit = bit + size;
  105. for (; bit < end_bit; ++bit)
  106. {
  107. rt_bitmap_clear_bit(mem->map, bit);
  108. }
  109. }
  110. void *rt_pci_ep_mem_alloc(struct rt_pci_ep *ep,
  111. rt_ubase_t *out_cpu_addr, rt_size_t size)
  112. {
  113. void *vaddr = RT_NULL;
  114. if (!ep || !out_cpu_addr)
  115. {
  116. return vaddr;
  117. }
  118. rt_mutex_take(&ep->lock, RT_WAITING_FOREVER);
  119. for (rt_size_t idx = 0; idx < ep->mems_nr; ++idx)
  120. {
  121. rt_ubase_t cpu_addr;
  122. struct rt_pci_ep_mem *mem = &ep->mems[idx];
  123. cpu_addr = bitmap_region_alloc(mem, size);
  124. if (cpu_addr != ~0ULL)
  125. {
  126. vaddr = rt_ioremap((void *)cpu_addr, size);
  127. if (!vaddr)
  128. {
  129. bitmap_region_free(mem, cpu_addr, size);
  130. /* Try next memory */
  131. continue;
  132. }
  133. *out_cpu_addr = cpu_addr;
  134. break;
  135. }
  136. }
  137. rt_mutex_release(&ep->lock);
  138. return vaddr;
  139. }
  140. void rt_pci_ep_mem_free(struct rt_pci_ep *ep,
  141. void *vaddr, rt_ubase_t cpu_addr, rt_size_t size)
  142. {
  143. if (!ep || !vaddr || !size)
  144. {
  145. return;
  146. }
  147. rt_mutex_take(&ep->lock, RT_WAITING_FOREVER);
  148. for (rt_size_t idx = 0; idx < ep->mems_nr; ++idx)
  149. {
  150. struct rt_pci_ep_mem *mem = &ep->mems[idx];
  151. if (mem->cpu_addr > cpu_addr &&
  152. mem->cpu_addr + mem->size >= cpu_addr + size)
  153. {
  154. rt_iounmap(mem);
  155. bitmap_region_free(mem, cpu_addr, size);
  156. break;
  157. }
  158. }
  159. rt_mutex_release(&ep->lock);
  160. }