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