diff options
Diffstat (limited to 'arch/sparc64/kernel/pci_iommu.c')
-rw-r--r-- | arch/sparc64/kernel/pci_iommu.c | 54 |
1 files changed, 50 insertions, 4 deletions
diff --git a/arch/sparc64/kernel/pci_iommu.c b/arch/sparc64/kernel/pci_iommu.c index 425c60cfea19..cdee7d9fed72 100644 --- a/arch/sparc64/kernel/pci_iommu.c +++ b/arch/sparc64/kernel/pci_iommu.c | |||
@@ -80,13 +80,59 @@ static void inline iopte_make_dummy(struct pci_iommu *iommu, iopte_t *iopte) | |||
80 | iopte_val(*iopte) = val; | 80 | iopte_val(*iopte) = val; |
81 | } | 81 | } |
82 | 82 | ||
83 | void pci_iommu_table_init(struct pci_iommu *iommu, int tsbsize) | 83 | void pci_iommu_table_init(struct pci_iommu *iommu, int tsbsize, u32 dma_offset, u32 dma_addr_mask) |
84 | { | 84 | { |
85 | int i; | 85 | unsigned long i, tsbbase, order; |
86 | |||
87 | /* Setup initial software IOMMU state. */ | ||
88 | spin_lock_init(&iommu->lock); | ||
89 | iommu->ctx_lowest_free = 1; | ||
90 | iommu->page_table_map_base = dma_offset; | ||
91 | iommu->dma_addr_mask = dma_addr_mask; | ||
92 | |||
93 | switch (tsbsize / (8 * 1024)) { | ||
94 | case 64: | ||
95 | iommu->page_table_sz_bits = 16; | ||
96 | break; | ||
97 | case 128: | ||
98 | iommu->page_table_sz_bits = 17; | ||
99 | break; | ||
100 | default: | ||
101 | prom_printf("PCI_IOMMU: Illegal TSB size %d\n", | ||
102 | tsbsize / (8 * 1024)); | ||
103 | prom_halt(); | ||
104 | break; | ||
105 | }; | ||
106 | |||
107 | iommu->lowest_consistent_map = | ||
108 | 1 << (iommu->page_table_sz_bits - PBM_LOGCLUSTERS); | ||
109 | |||
110 | for (i = 0; i < PBM_NCLUSTERS; i++) { | ||
111 | iommu->alloc_info[i].flush = 0; | ||
112 | iommu->alloc_info[i].next = 0; | ||
113 | } | ||
86 | 114 | ||
87 | tsbsize /= sizeof(iopte_t); | 115 | /* Allocate and initialize the dummy page which we |
116 | * set inactive IO PTEs to point to. | ||
117 | */ | ||
118 | iommu->dummy_page = __get_free_pages(GFP_KERNEL, 0); | ||
119 | if (!iommu->dummy_page) { | ||
120 | prom_printf("PCI_IOMMU: Error, gfp(dummy_page) failed.\n"); | ||
121 | prom_halt(); | ||
122 | } | ||
123 | memset((void *)iommu->dummy_page, 0, PAGE_SIZE); | ||
124 | iommu->dummy_page_pa = (unsigned long) __pa(iommu->dummy_page); | ||
125 | |||
126 | /* Now allocate and setup the IOMMU page table itself. */ | ||
127 | order = get_order(tsbsize); | ||
128 | tsbbase = __get_free_pages(GFP_KERNEL, order); | ||
129 | if (!tsbbase) { | ||
130 | prom_printf("PCI_IOMMU: Error, gfp(tsb) failed.\n"); | ||
131 | prom_halt(); | ||
132 | } | ||
133 | iommu->page_table = (iopte_t *)tsbbase; | ||
88 | 134 | ||
89 | for (i = 0; i < tsbsize; i++) | 135 | for (i = 0; i < tsbsize / sizeof(iopte_t); i++) |
90 | iopte_make_dummy(iommu, &iommu->page_table[i]); | 136 | iopte_make_dummy(iommu, &iommu->page_table[i]); |
91 | } | 137 | } |
92 | 138 | ||