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