diff options
| -rw-r--r-- | arch/sparc64/kernel/pci_iommu.c | 54 | ||||
| -rw-r--r-- | arch/sparc64/kernel/pci_psycho.c | 44 | ||||
| -rw-r--r-- | arch/sparc64/kernel/pci_sabre.c | 39 | ||||
| -rw-r--r-- | arch/sparc64/kernel/pci_schizo.c | 57 | ||||
| -rw-r--r-- | include/asm-sparc64/pbm.h | 2 |
5 files changed, 63 insertions, 133 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 | ||
diff --git a/arch/sparc64/kernel/pci_psycho.c b/arch/sparc64/kernel/pci_psycho.c index 6ed1ef25e0ac..c03ed5f49d31 100644 --- a/arch/sparc64/kernel/pci_psycho.c +++ b/arch/sparc64/kernel/pci_psycho.c | |||
| @@ -1207,13 +1207,9 @@ static void psycho_scan_bus(struct pci_controller_info *p) | |||
| 1207 | static void psycho_iommu_init(struct pci_controller_info *p) | 1207 | static void psycho_iommu_init(struct pci_controller_info *p) |
| 1208 | { | 1208 | { |
| 1209 | struct pci_iommu *iommu = p->pbm_A.iommu; | 1209 | struct pci_iommu *iommu = p->pbm_A.iommu; |
| 1210 | unsigned long tsbbase, i; | 1210 | unsigned long i; |
| 1211 | u64 control; | 1211 | u64 control; |
| 1212 | 1212 | ||
| 1213 | /* Setup initial software IOMMU state. */ | ||
| 1214 | spin_lock_init(&iommu->lock); | ||
| 1215 | iommu->ctx_lowest_free = 1; | ||
| 1216 | |||
| 1217 | /* Register addresses. */ | 1213 | /* Register addresses. */ |
| 1218 | iommu->iommu_control = p->pbm_A.controller_regs + PSYCHO_IOMMU_CONTROL; | 1214 | iommu->iommu_control = p->pbm_A.controller_regs + PSYCHO_IOMMU_CONTROL; |
| 1219 | iommu->iommu_tsbbase = p->pbm_A.controller_regs + PSYCHO_IOMMU_TSBBASE; | 1215 | iommu->iommu_tsbbase = p->pbm_A.controller_regs + PSYCHO_IOMMU_TSBBASE; |
| @@ -1240,40 +1236,10 @@ static void psycho_iommu_init(struct pci_controller_info *p) | |||
| 1240 | /* Leave diag mode enabled for full-flushing done | 1236 | /* Leave diag mode enabled for full-flushing done |
| 1241 | * in pci_iommu.c | 1237 | * in pci_iommu.c |
| 1242 | */ | 1238 | */ |
| 1239 | pci_iommu_table_init(iommu, IO_TSB_SIZE, 0xc0000000, 0xffffffff); | ||
| 1243 | 1240 | ||
| 1244 | iommu->dummy_page = __get_free_pages(GFP_KERNEL, 0); | 1241 | psycho_write(p->pbm_A.controller_regs + PSYCHO_IOMMU_TSBBASE, |
| 1245 | if (!iommu->dummy_page) { | 1242 | __pa(iommu->page_table)); |
| 1246 | prom_printf("PSYCHO_IOMMU: Error, gfp(dummy_page) failed.\n"); | ||
| 1247 | prom_halt(); | ||
| 1248 | } | ||
| 1249 | memset((void *)iommu->dummy_page, 0, PAGE_SIZE); | ||
| 1250 | iommu->dummy_page_pa = (unsigned long) __pa(iommu->dummy_page); | ||
| 1251 | |||
| 1252 | /* Using assumed page size 8K with 128K entries we need 1MB iommu page | ||
| 1253 | * table (128K ioptes * 8 bytes per iopte). This is | ||
| 1254 | * page order 7 on UltraSparc. | ||
| 1255 | */ | ||
| 1256 | tsbbase = __get_free_pages(GFP_KERNEL, get_order(IO_TSB_SIZE)); | ||
| 1257 | if (!tsbbase) { | ||
| 1258 | prom_printf("PSYCHO_IOMMU: Error, gfp(tsb) failed.\n"); | ||
| 1259 | prom_halt(); | ||
| 1260 | } | ||
| 1261 | iommu->page_table = (iopte_t *)tsbbase; | ||
| 1262 | iommu->page_table_sz_bits = 17; | ||
| 1263 | iommu->page_table_map_base = 0xc0000000; | ||
| 1264 | iommu->dma_addr_mask = 0xffffffff; | ||
| 1265 | pci_iommu_table_init(iommu, IO_TSB_SIZE); | ||
| 1266 | |||
| 1267 | /* We start with no consistent mappings. */ | ||
| 1268 | iommu->lowest_consistent_map = | ||
| 1269 | 1 << (iommu->page_table_sz_bits - PBM_LOGCLUSTERS); | ||
| 1270 | |||
| 1271 | for (i = 0; i < PBM_NCLUSTERS; i++) { | ||
| 1272 | iommu->alloc_info[i].flush = 0; | ||
| 1273 | iommu->alloc_info[i].next = 0; | ||
| 1274 | } | ||
| 1275 | |||
| 1276 | psycho_write(p->pbm_A.controller_regs + PSYCHO_IOMMU_TSBBASE, __pa(tsbbase)); | ||
| 1277 | 1243 | ||
| 1278 | control = psycho_read(p->pbm_A.controller_regs + PSYCHO_IOMMU_CONTROL); | 1244 | control = psycho_read(p->pbm_A.controller_regs + PSYCHO_IOMMU_CONTROL); |
| 1279 | control &= ~(PSYCHO_IOMMU_CTRL_TSBSZ | PSYCHO_IOMMU_CTRL_TBWSZ); | 1245 | control &= ~(PSYCHO_IOMMU_CTRL_TSBSZ | PSYCHO_IOMMU_CTRL_TBWSZ); |
| @@ -1281,7 +1247,7 @@ static void psycho_iommu_init(struct pci_controller_info *p) | |||
| 1281 | psycho_write(p->pbm_A.controller_regs + PSYCHO_IOMMU_CONTROL, control); | 1247 | psycho_write(p->pbm_A.controller_regs + PSYCHO_IOMMU_CONTROL, control); |
| 1282 | 1248 | ||
| 1283 | /* If necessary, hook us up for starfire IRQ translations. */ | 1249 | /* If necessary, hook us up for starfire IRQ translations. */ |
| 1284 | if(this_is_starfire) | 1250 | if (this_is_starfire) |
| 1285 | p->starfire_cookie = starfire_hookup(p->pbm_A.portid); | 1251 | p->starfire_cookie = starfire_hookup(p->pbm_A.portid); |
| 1286 | else | 1252 | else |
| 1287 | p->starfire_cookie = NULL; | 1253 | p->starfire_cookie = NULL; |
diff --git a/arch/sparc64/kernel/pci_sabre.c b/arch/sparc64/kernel/pci_sabre.c index 0ee6bd5b9ac6..da8e1364194f 100644 --- a/arch/sparc64/kernel/pci_sabre.c +++ b/arch/sparc64/kernel/pci_sabre.c | |||
| @@ -1267,13 +1267,9 @@ static void sabre_iommu_init(struct pci_controller_info *p, | |||
| 1267 | u32 dma_mask) | 1267 | u32 dma_mask) |
| 1268 | { | 1268 | { |
| 1269 | struct pci_iommu *iommu = p->pbm_A.iommu; | 1269 | struct pci_iommu *iommu = p->pbm_A.iommu; |
| 1270 | unsigned long tsbbase, i, order; | 1270 | unsigned long i; |
| 1271 | u64 control; | 1271 | u64 control; |
| 1272 | 1272 | ||
| 1273 | /* Setup initial software IOMMU state. */ | ||
| 1274 | spin_lock_init(&iommu->lock); | ||
| 1275 | iommu->ctx_lowest_free = 1; | ||
| 1276 | |||
| 1277 | /* Register addresses. */ | 1273 | /* Register addresses. */ |
| 1278 | iommu->iommu_control = p->pbm_A.controller_regs + SABRE_IOMMU_CONTROL; | 1274 | iommu->iommu_control = p->pbm_A.controller_regs + SABRE_IOMMU_CONTROL; |
| 1279 | iommu->iommu_tsbbase = p->pbm_A.controller_regs + SABRE_IOMMU_TSBBASE; | 1275 | iommu->iommu_tsbbase = p->pbm_A.controller_regs + SABRE_IOMMU_TSBBASE; |
| @@ -1295,26 +1291,10 @@ static void sabre_iommu_init(struct pci_controller_info *p, | |||
| 1295 | /* Leave diag mode enabled for full-flushing done | 1291 | /* Leave diag mode enabled for full-flushing done |
| 1296 | * in pci_iommu.c | 1292 | * in pci_iommu.c |
| 1297 | */ | 1293 | */ |
| 1294 | pci_iommu_table_init(iommu, tsbsize * 1024 * 8, dvma_offset, dma_mask); | ||
| 1298 | 1295 | ||
| 1299 | iommu->dummy_page = __get_free_pages(GFP_KERNEL, 0); | 1296 | sabre_write(p->pbm_A.controller_regs + SABRE_IOMMU_TSBBASE, |
| 1300 | if (!iommu->dummy_page) { | 1297 | __pa(iommu->page_table)); |
| 1301 | prom_printf("PSYCHO_IOMMU: Error, gfp(dummy_page) failed.\n"); | ||
| 1302 | prom_halt(); | ||
| 1303 | } | ||
| 1304 | memset((void *)iommu->dummy_page, 0, PAGE_SIZE); | ||
| 1305 | iommu->dummy_page_pa = (unsigned long) __pa(iommu->dummy_page); | ||
| 1306 | |||
| 1307 | tsbbase = __get_free_pages(GFP_KERNEL, order = get_order(tsbsize * 1024 * 8)); | ||
| 1308 | if (!tsbbase) { | ||
| 1309 | prom_printf("SABRE_IOMMU: Error, gfp(tsb) failed.\n"); | ||
| 1310 | prom_halt(); | ||
| 1311 | } | ||
| 1312 | iommu->page_table = (iopte_t *)tsbbase; | ||
| 1313 | iommu->page_table_map_base = dvma_offset; | ||
| 1314 | iommu->dma_addr_mask = dma_mask; | ||
| 1315 | pci_iommu_table_init(iommu, PAGE_SIZE << order); | ||
| 1316 | |||
| 1317 | sabre_write(p->pbm_A.controller_regs + SABRE_IOMMU_TSBBASE, __pa(tsbbase)); | ||
| 1318 | 1298 | ||
| 1319 | control = sabre_read(p->pbm_A.controller_regs + SABRE_IOMMU_CONTROL); | 1299 | control = sabre_read(p->pbm_A.controller_regs + SABRE_IOMMU_CONTROL); |
| 1320 | control &= ~(SABRE_IOMMUCTRL_TSBSZ | SABRE_IOMMUCTRL_TBWSZ); | 1300 | control &= ~(SABRE_IOMMUCTRL_TSBSZ | SABRE_IOMMUCTRL_TBWSZ); |
| @@ -1322,11 +1302,9 @@ static void sabre_iommu_init(struct pci_controller_info *p, | |||
| 1322 | switch(tsbsize) { | 1302 | switch(tsbsize) { |
| 1323 | case 64: | 1303 | case 64: |
| 1324 | control |= SABRE_IOMMU_TSBSZ_64K; | 1304 | control |= SABRE_IOMMU_TSBSZ_64K; |
| 1325 | iommu->page_table_sz_bits = 16; | ||
| 1326 | break; | 1305 | break; |
| 1327 | case 128: | 1306 | case 128: |
| 1328 | control |= SABRE_IOMMU_TSBSZ_128K; | 1307 | control |= SABRE_IOMMU_TSBSZ_128K; |
| 1329 | iommu->page_table_sz_bits = 17; | ||
| 1330 | break; | 1308 | break; |
| 1331 | default: | 1309 | default: |
| 1332 | prom_printf("iommu_init: Illegal TSB size %d\n", tsbsize); | 1310 | prom_printf("iommu_init: Illegal TSB size %d\n", tsbsize); |
| @@ -1334,15 +1312,6 @@ static void sabre_iommu_init(struct pci_controller_info *p, | |||
| 1334 | break; | 1312 | break; |
| 1335 | } | 1313 | } |
| 1336 | sabre_write(p->pbm_A.controller_regs + SABRE_IOMMU_CONTROL, control); | 1314 | sabre_write(p->pbm_A.controller_regs + SABRE_IOMMU_CONTROL, control); |
| 1337 | |||
| 1338 | /* We start with no consistent mappings. */ | ||
| 1339 | iommu->lowest_consistent_map = | ||
| 1340 | 1 << (iommu->page_table_sz_bits - PBM_LOGCLUSTERS); | ||
| 1341 | |||
| 1342 | for (i = 0; i < PBM_NCLUSTERS; i++) { | ||
| 1343 | iommu->alloc_info[i].flush = 0; | ||
| 1344 | iommu->alloc_info[i].next = 0; | ||
| 1345 | } | ||
| 1346 | } | 1315 | } |
| 1347 | 1316 | ||
| 1348 | static void pbm_register_toplevel_resources(struct pci_controller_info *p, | 1317 | static void pbm_register_toplevel_resources(struct pci_controller_info *p, |
diff --git a/arch/sparc64/kernel/pci_schizo.c b/arch/sparc64/kernel/pci_schizo.c index cae5b61fe2f0..d8c4e0919b4e 100644 --- a/arch/sparc64/kernel/pci_schizo.c +++ b/arch/sparc64/kernel/pci_schizo.c | |||
| @@ -1765,7 +1765,7 @@ static void schizo_pbm_strbuf_init(struct pci_pbm_info *pbm) | |||
| 1765 | static void schizo_pbm_iommu_init(struct pci_pbm_info *pbm) | 1765 | static void schizo_pbm_iommu_init(struct pci_pbm_info *pbm) |
| 1766 | { | 1766 | { |
| 1767 | struct pci_iommu *iommu = pbm->iommu; | 1767 | struct pci_iommu *iommu = pbm->iommu; |
| 1768 | unsigned long tsbbase, i, tagbase, database, order; | 1768 | unsigned long i, tagbase, database; |
| 1769 | u32 vdma[2], dma_mask; | 1769 | u32 vdma[2], dma_mask; |
| 1770 | u64 control; | 1770 | u64 control; |
| 1771 | int err, tsbsize; | 1771 | int err, tsbsize; |
| @@ -1800,10 +1800,6 @@ static void schizo_pbm_iommu_init(struct pci_pbm_info *pbm) | |||
| 1800 | prom_halt(); | 1800 | prom_halt(); |
| 1801 | }; | 1801 | }; |
| 1802 | 1802 | ||
| 1803 | /* Setup initial software IOMMU state. */ | ||
| 1804 | spin_lock_init(&iommu->lock); | ||
| 1805 | iommu->ctx_lowest_free = 1; | ||
| 1806 | |||
| 1807 | /* Register addresses, SCHIZO has iommu ctx flushing. */ | 1803 | /* Register addresses, SCHIZO has iommu ctx flushing. */ |
| 1808 | iommu->iommu_control = pbm->pbm_regs + SCHIZO_IOMMU_CONTROL; | 1804 | iommu->iommu_control = pbm->pbm_regs + SCHIZO_IOMMU_CONTROL; |
| 1809 | iommu->iommu_tsbbase = pbm->pbm_regs + SCHIZO_IOMMU_TSBBASE; | 1805 | iommu->iommu_tsbbase = pbm->pbm_regs + SCHIZO_IOMMU_TSBBASE; |
| @@ -1832,56 +1828,9 @@ static void schizo_pbm_iommu_init(struct pci_pbm_info *pbm) | |||
| 1832 | /* Leave diag mode enabled for full-flushing done | 1828 | /* Leave diag mode enabled for full-flushing done |
| 1833 | * in pci_iommu.c | 1829 | * in pci_iommu.c |
| 1834 | */ | 1830 | */ |
| 1831 | pci_iommu_table_init(iommu, tsbsize * 8 * 1024, vdma[0], dma_mask); | ||
| 1835 | 1832 | ||
| 1836 | iommu->dummy_page = __get_free_pages(GFP_KERNEL, 0); | 1833 | schizo_write(iommu->iommu_tsbbase, __pa(iommu->page_table)); |
| 1837 | if (!iommu->dummy_page) { | ||
| 1838 | prom_printf("PSYCHO_IOMMU: Error, gfp(dummy_page) failed.\n"); | ||
| 1839 | prom_halt(); | ||
| 1840 | } | ||
| 1841 | memset((void *)iommu->dummy_page, 0, PAGE_SIZE); | ||
| 1842 | iommu->dummy_page_pa = (unsigned long) __pa(iommu->dummy_page); | ||
| 1843 | |||
| 1844 | /* Using assumed page size 8K with 128K entries we need 1MB iommu page | ||
| 1845 | * table (128K ioptes * 8 bytes per iopte). This is | ||
| 1846 | * page order 7 on UltraSparc. | ||
| 1847 | */ | ||
| 1848 | order = get_order(tsbsize * 8 * 1024); | ||
| 1849 | tsbbase = __get_free_pages(GFP_KERNEL, order); | ||
| 1850 | if (!tsbbase) { | ||
| 1851 | prom_printf("%s: Error, gfp(tsb) failed.\n", pbm->name); | ||
| 1852 | prom_halt(); | ||
| 1853 | } | ||
| 1854 | |||
| 1855 | iommu->page_table = (iopte_t *)tsbbase; | ||
| 1856 | iommu->page_table_map_base = vdma[0]; | ||
| 1857 | iommu->dma_addr_mask = dma_mask; | ||
| 1858 | pci_iommu_table_init(iommu, PAGE_SIZE << order); | ||
| 1859 | |||
| 1860 | switch (tsbsize) { | ||
| 1861 | case 64: | ||
| 1862 | iommu->page_table_sz_bits = 16; | ||
| 1863 | break; | ||
| 1864 | |||
| 1865 | case 128: | ||
| 1866 | iommu->page_table_sz_bits = 17; | ||
| 1867 | break; | ||
| 1868 | |||
| 1869 | default: | ||
| 1870 | prom_printf("iommu_init: Illegal TSB size %d\n", tsbsize); | ||
| 1871 | prom_halt(); | ||
| 1872 | break; | ||
| 1873 | }; | ||
| 1874 | |||
| 1875 | /* We start with no consistent mappings. */ | ||
| 1876 | iommu->lowest_consistent_map = | ||
| 1877 | 1 << (iommu->page_table_sz_bits - PBM_LOGCLUSTERS); | ||
| 1878 | |||
| 1879 | for (i = 0; i < PBM_NCLUSTERS; i++) { | ||
| 1880 | iommu->alloc_info[i].flush = 0; | ||
| 1881 | iommu->alloc_info[i].next = 0; | ||
| 1882 | } | ||
| 1883 | |||
| 1884 | schizo_write(iommu->iommu_tsbbase, __pa(tsbbase)); | ||
| 1885 | 1834 | ||
| 1886 | control = schizo_read(iommu->iommu_control); | 1835 | control = schizo_read(iommu->iommu_control); |
| 1887 | control &= ~(SCHIZO_IOMMU_CTRL_TSBSZ | SCHIZO_IOMMU_CTRL_TBWSZ); | 1836 | control &= ~(SCHIZO_IOMMU_CTRL_TSBSZ | SCHIZO_IOMMU_CTRL_TBWSZ); |
diff --git a/include/asm-sparc64/pbm.h b/include/asm-sparc64/pbm.h index 38bbbccb4068..c067407de0b0 100644 --- a/include/asm-sparc64/pbm.h +++ b/include/asm-sparc64/pbm.h | |||
| @@ -102,7 +102,7 @@ struct pci_iommu { | |||
| 102 | u32 dma_addr_mask; | 102 | u32 dma_addr_mask; |
| 103 | }; | 103 | }; |
| 104 | 104 | ||
| 105 | extern void pci_iommu_table_init(struct pci_iommu *, int); | 105 | extern void pci_iommu_table_init(struct pci_iommu *iommu, int tsbsize, u32 dma_offset, u32 dma_addr_mask); |
| 106 | 106 | ||
| 107 | /* This describes a PCI bus module's streaming buffer. */ | 107 | /* This describes a PCI bus module's streaming buffer. */ |
| 108 | struct pci_strbuf { | 108 | struct pci_strbuf { |
