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