aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sparc64/kernel/pci_iommu.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sparc64/kernel/pci_iommu.c')
-rw-r--r--arch/sparc64/kernel/pci_iommu.c54
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
83void pci_iommu_table_init(struct pci_iommu *iommu, int tsbsize) 83void 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