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