pci-iommu_table.c 1.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. // SPDX-License-Identifier: GPL-2.0
  2. #include <linux/dma-mapping.h>
  3. #include <asm/iommu_table.h>
  4. #include <linux/string.h>
  5. #include <linux/kallsyms.h>
  6. #define DEBUG 1
  7. static struct iommu_table_entry * __init
  8. find_dependents_of(struct iommu_table_entry *start,
  9. struct iommu_table_entry *finish,
  10. struct iommu_table_entry *q)
  11. {
  12. struct iommu_table_entry *p;
  13. if (!q)
  14. return NULL;
  15. for (p = start; p < finish; p++)
  16. if (p->detect == q->depend)
  17. return p;
  18. return NULL;
  19. }
  20. void __init sort_iommu_table(struct iommu_table_entry *start,
  21. struct iommu_table_entry *finish) {
  22. struct iommu_table_entry *p, *q, tmp;
  23. for (p = start; p < finish; p++) {
  24. again:
  25. q = find_dependents_of(start, finish, p);
  26. /* We are bit sneaky here. We use the memory address to figure
  27. * out if the node we depend on is past our point, if so, swap.
  28. */
  29. if (q > p) {
  30. tmp = *p;
  31. memmove(p, q, sizeof(*p));
  32. *q = tmp;
  33. goto again;
  34. }
  35. }
  36. }
  37. #ifdef DEBUG
  38. void __init check_iommu_entries(struct iommu_table_entry *start,
  39. struct iommu_table_entry *finish)
  40. {
  41. struct iommu_table_entry *p, *q, *x;
  42. /* Simple cyclic dependency checker. */
  43. for (p = start; p < finish; p++) {
  44. q = find_dependents_of(start, finish, p);
  45. x = find_dependents_of(start, finish, q);
  46. if (p == x) {
  47. printk(KERN_ERR "CYCLIC DEPENDENCY FOUND! %pS depends on %pS and vice-versa. BREAKING IT.\n",
  48. p->detect, q->detect);
  49. /* Heavy handed way..*/
  50. x->depend = NULL;
  51. }
  52. }
  53. for (p = start; p < finish; p++) {
  54. q = find_dependents_of(p, finish, p);
  55. if (q && q > p) {
  56. printk(KERN_ERR "EXECUTION ORDER INVALID! %pS should be called before %pS!\n",
  57. p->detect, q->detect);
  58. }
  59. }
  60. }
  61. #else
  62. void __init check_iommu_entries(struct iommu_table_entry *start,
  63. struct iommu_table_entry *finish)
  64. {
  65. }
  66. #endif