25 #define pr_fmt(fmt) "Calgary: " fmt
27 #include <linux/kernel.h>
29 #include <linux/types.h>
30 #include <linux/slab.h>
33 #include <linux/string.h>
36 #include <linux/bitmap.h>
38 #include <linux/pci.h>
43 #include <asm/iommu.h>
51 #include <asm/iommu_table.h>
53 #ifdef CONFIG_CALGARY_IOMMU_ENABLED_BY_DEFAULT
59 #define PCI_DEVICE_ID_IBM_CALGARY 0x02a1
60 #define PCI_DEVICE_ID_IBM_CALIOC2 0x0308
63 #define CALGARY_CONFIG_REG 0x0108
64 #define PHB_CSR_OFFSET 0x0110
65 #define PHB_PLSSR_OFFSET 0x0120
66 #define PHB_CONFIG_RW_OFFSET 0x0160
67 #define PHB_IOBASE_BAR_LOW 0x0170
68 #define PHB_IOBASE_BAR_HIGH 0x0180
69 #define PHB_MEM_1_LOW 0x0190
70 #define PHB_MEM_1_HIGH 0x01A0
71 #define PHB_IO_ADDR_SIZE 0x01B0
72 #define PHB_MEM_1_SIZE 0x01C0
73 #define PHB_MEM_ST_OFFSET 0x01D0
74 #define PHB_AER_OFFSET 0x0200
75 #define PHB_CONFIG_0_HIGH 0x0220
76 #define PHB_CONFIG_0_LOW 0x0230
77 #define PHB_CONFIG_0_END 0x0240
78 #define PHB_MEM_2_LOW 0x02B0
79 #define PHB_MEM_2_HIGH 0x02C0
80 #define PHB_MEM_2_SIZE_HIGH 0x02D0
81 #define PHB_MEM_2_SIZE_LOW 0x02E0
82 #define PHB_DOSHOLE_OFFSET 0x08E0
85 #define PHB_SAVIOR_L2 0x0DB0
86 #define PHB_PAGE_MIG_CTRL 0x0DA8
87 #define PHB_PAGE_MIG_DEBUG 0x0DA0
88 #define PHB_ROOT_COMPLEX_STATUS 0x0CB0
91 #define PHB_TCE_ENABLE 0x20000000
92 #define PHB_SLOT_DISABLE 0x1C000000
93 #define PHB_DAC_DISABLE 0x01000000
94 #define PHB_MEM2_ENABLE 0x00400000
95 #define PHB_MCSR_ENABLE 0x00100000
97 #define TAR_SW_BITS 0x0000ffffffff800fUL
98 #define TAR_VALID 0x0000000000000008UL
100 #define CSR_AGENT_MASK 0xffe0ffff
102 #define CCR_2SEC_TIMEOUT 0x000000000000000EUL
104 #define PMR_SOFTSTOP 0x80000000
105 #define PMR_SOFTSTOPFAULT 0x40000000
106 #define PMR_HARDSTOP 0x20000000
115 #define MAX_PHB_BUS_NUM 256
117 #define PHBS_PER_CALGARY 4
120 static const unsigned long tar_offsets[] = {
127 static const unsigned long split_queue_offsets[] = {
134 static const unsigned long phb_offsets[] = {
143 static const unsigned long phb_debug_offsets[] = {
155 #define PHB_DEBUG_STUFF_OFFSET 0x0020
157 #define EMERGENCY_PAGES 32
175 static void calgary_tce_cache_blast(
struct iommu_table *tbl);
176 static void calgary_dump_error_regs(
struct iommu_table *tbl);
178 static void calioc2_tce_cache_blast(
struct iommu_table *tbl);
179 static void calioc2_dump_error_regs(
struct iommu_table *tbl);
180 static void calgary_init_bitmap_from_tce_table(
struct iommu_table *tbl);
181 static void get_tce_space_from_tar(
void);
184 .handle_quirks = calgary_handle_quirks,
185 .tce_cache_blast = calgary_tce_cache_blast,
186 .dump_error_regs = calgary_dump_error_regs
190 .handle_quirks = calioc2_handle_quirks,
191 .tce_cache_blast = calioc2_tce_cache_blast,
192 .dump_error_regs = calioc2_dump_error_regs
197 static inline int translation_enabled(
struct iommu_table *tbl)
200 return (tbl !=
NULL);
203 static void iommu_range_reserve(
struct iommu_table *tbl,
204 unsigned long start_addr,
unsigned int npages)
216 end = index + npages;
224 spin_unlock_irqrestore(&tbl->
it_lock, flags);
233 unsigned long boundary_size;
235 boundary_size =
ALIGN(dma_get_seg_boundary(dev) + 1,
243 npages, 0, boundary_size, 0);
244 if (offset == ~0
UL) {
245 tbl->
chip_ops->tce_cache_blast(tbl);
248 npages, 0, boundary_size, 0);
249 if (offset == ~0
UL) {
251 spin_unlock_irqrestore(&tbl->
it_lock, flags);
252 if (panic_on_overflow)
253 panic(
"Calgary: fix the allocator.\n");
259 tbl->
it_hint = offset + npages;
262 spin_unlock_irqrestore(&tbl->
it_lock, flags);
276 pr_warn(
"failed to allocate %u pages in iommu %p\n",
294 unsigned long badend;
300 WARN(1,
KERN_ERR "Calgary: driver tried unmapping bad DMA "
301 "address 0x%Lx\n", dma_addr);
315 spin_unlock_irqrestore(&tbl->
it_lock, flags);
329 tbl = pci_iommu(pbus);
349 if (!translation_enabled(tbl))
355 unsigned int dmalen = s->dma_length;
360 npages = iommu_num_pages(dma, dmalen,
PAGE_SIZE);
361 iommu_free(tbl, dma, npages);
379 vaddr = (
unsigned long) sg_virt(s);
394 s->dma_length = s->
length;
399 calgary_unmap_sg(dev, sg, nelems, dir,
NULL);
408 unsigned long offset,
size_t size,
417 uaddr = (
unsigned long)vaddr;
418 npages = iommu_num_pages(uaddr, size,
PAGE_SIZE);
420 return iommu_alloc(dev, tbl, vaddr, npages, dir);
430 npages = iommu_num_pages(dma_addr, size,
PAGE_SIZE);
431 iommu_free(tbl, dma_addr, npages);
434 static void* calgary_alloc_coherent(
struct device *dev,
size_t size,
439 unsigned int npages,
order;
467 static void calgary_free_coherent(
struct device *dev,
size_t size,
477 iommu_free(tbl, dma_handle, npages);
482 .alloc = calgary_alloc_coherent,
483 .free = calgary_free_coherent,
484 .map_sg = calgary_map_sg,
485 .unmap_sg = calgary_unmap_sg,
486 .map_page = calgary_map_page,
487 .unmap_page = calgary_unmap_page,
490 static inline void __iomem * busno_to_bbar(
unsigned char num)
492 return bus_info[num].
bbar;
495 static inline int busno_to_phbid(
unsigned char num)
497 return bus_info[num].
phbid;
500 static inline unsigned long split_queue_offset(
unsigned char num)
502 size_t idx = busno_to_phbid(num);
504 return split_queue_offsets[
idx];
507 static inline unsigned long tar_offset(
unsigned char num)
509 size_t idx = busno_to_phbid(num);
511 return tar_offsets[
idx];
514 static inline unsigned long phb_offset(
unsigned char num)
516 size_t idx = busno_to_phbid(num);
518 return phb_offsets[
idx];
521 static inline void __iomem* calgary_reg(
void __iomem *bar,
unsigned long offset)
527 static inline int is_calioc2(
unsigned short device)
532 static inline int is_calgary(
unsigned short device)
537 static inline int is_cal_pci_dev(
unsigned short device)
539 return (is_calgary(device) || is_calioc2(device));
542 static void calgary_tce_cache_blast(
struct iommu_table *tbl)
560 target = calgary_reg(bbar, split_queue_offset(tbl->
it_busno));
564 }
while ((val & 0xff) != 0xff && i < 100);
566 pr_warn(
"PCI bus not quiesced, continuing anyway\n");
569 target = calgary_reg(bbar, tar_offset(tbl->
it_busno));
578 static void calioc2_tce_cache_blast(
struct iommu_table *tbl)
590 "sequence - count %d\n", bus, count);
602 target = calgary_reg(bbar, split_queue_offset(bus));
604 val64 =
readq(target);
606 }
while ((val64 & 0xff) != 0xff && i < 100);
608 pr_warn(
"CalIOC2: PCI bus not quiesced, continuing anyway\n");
620 pr_warn(
"CalIOC2: too many SoftStopFaults, aborting TCE cache flush sequence!\n");
636 target = calgary_reg(bbar, tar_offset(bus));
658 unsigned int numpages;
660 limit = limit | 0xfffff;
663 numpages = ((limit -
start) >> PAGE_SHIFT);
664 iommu_range_reserve(pci_iommu(dev->
bus), start, numpages);
667 static void __init calgary_reserve_peripheral_mem_1(
struct pci_dev *dev)
677 target = calgary_reg(bbar, phb_offset(busnum) |
PHB_MEM_1_LOW);
684 start = (high << 32) | low;
687 calgary_reserve_mem_region(dev, start, limit);
690 static void __init calgary_reserve_peripheral_mem_2(
struct pci_dev *dev)
697 unsigned char busnum = dev->
bus->number;
706 target = calgary_reg(bbar, phb_offset(busnum) |
PHB_MEM_2_LOW);
715 start = (high << 32) | low;
716 limit = (sizehigh << 32) | sizelow;
718 calgary_reserve_mem_region(dev, start, limit);
728 static void __init calgary_reserve_regions(
struct pci_dev *dev)
739 if (is_calgary(dev->
device)) {
740 start = (640 * 1024);
744 npages = (1 * 1024 * 1024) >> PAGE_SHIFT;
746 iommu_range_reserve(tbl, start, npages);
749 calgary_reserve_peripheral_mem_1(dev);
750 calgary_reserve_peripheral_mem_2(dev);
766 tbl = pci_iommu(dev->
bus);
769 if (is_kdump_kernel())
770 calgary_init_bitmap_from_tce_table(tbl);
774 if (is_calgary(dev->
device))
776 else if (is_calioc2(dev->
device))
781 calgary_reserve_regions(dev);
784 target = calgary_reg(bbar, tar_offset(dev->
bus->number));
809 unsigned int bitmapsz;
811 target = calgary_reg(tbl->
bbar, tar_offset(dev->
bus->number));
829 static void calgary_dump_error_regs(
struct iommu_table *tbl)
842 pr_emerg(
"DMA error on Calgary PHB 0x%x, 0x%08x@CSR 0x%08x@PLSSR\n",
846 static void calioc2_dump_error_regs(
struct iommu_table *tbl)
849 u32 csr, csmr, plssr,
mck, rcstat;
851 unsigned long phboff = phb_offset(tbl->
it_busno);
852 unsigned long erroff;
863 target = calgary_reg(bbar, phboff | 0x290);
866 target = calgary_reg(bbar, phboff | 0x800);
871 pr_emerg(
"0x%08x@CSR 0x%08x@PLSSR 0x%08x@CSMR 0x%08x@MCK\n",
872 csr, plssr, csmr, mck);
878 erroff = (0x810 + (i * 0x10));
879 target = calgary_reg(bbar, phboff | erroff);
881 pr_cont(
"0x%08x@0x%lx ", errregs[i], erroff);
892 static void calgary_watchdog(
unsigned long data)
905 tbl->
chip_ops->dump_error_regs(tbl);
911 target = calgary_reg(bbar, phb_offset(tbl->
it_busno) |
923 static void __init calgary_set_split_completion_timeout(
void __iomem *bbar,
924 unsigned char busnum,
unsigned long timeout)
928 unsigned int phb_shift = ~0;
931 switch (busno_to_phbid(busnum)) {
932 case 0: phb_shift = (63 - 19);
934 case 1: phb_shift = (63 - 23);
936 case 2: phb_shift = (63 - 27);
938 case 3: phb_shift = (63 - 35);
941 BUG_ON(busno_to_phbid(busnum));
948 mask = ~(0xF
UL << phb_shift);
950 val64 |= (timeout << phb_shift);
957 unsigned char busnum = dev->
bus->number;
965 target = calgary_reg(bbar, phb_offset(busnum) |
PHB_SAVIOR_L2);
973 unsigned char busnum = dev->
bus->number;
979 if (is_calgary(dev->
device) && (busnum == 1))
980 calgary_set_split_completion_timeout(tbl->
bbar, busnum,
984 static void __init calgary_enable_translation(
struct pci_dev *dev)
992 busnum = dev->
bus->number;
993 tbl = pci_iommu(dev->
bus);
1003 "Calgary" :
"CalIOC2", busnum);
1004 printk(
KERN_INFO "Calgary: errant DMAs will now be prevented on this "
1016 static void __init calgary_disable_translation(
struct pci_dev *dev)
1024 busnum = dev->
bus->number;
1025 tbl = pci_iommu(dev->
bus);
1033 printk(
KERN_INFO "Calgary: disabling translation on PHB %#x!\n", busnum);
1040 static void __init calgary_init_one_nontraslated(
struct pci_dev *dev)
1043 set_pci_iommu(dev->
bus,
NULL);
1046 if (dev->
bus->parent)
1047 dev->
bus->parent->self =
dev;
1058 bbar = busno_to_bbar(dev->
bus->number);
1059 ret = calgary_setup_tar(dev, bbar);
1065 if (dev->
bus->parent) {
1066 if (dev->
bus->parent->self)
1068 "bus->parent->self!\n", dev);
1069 dev->
bus->parent->self =
dev;
1073 tbl = pci_iommu(dev->
bus);
1074 tbl->
chip_ops->handle_quirks(tbl, dev);
1076 calgary_enable_translation(dev);
1084 static int __init calgary_locate_bbars(
void)
1087 int rioidx, phb,
bus;
1091 u8 start_bus, end_bus;
1108 target = calgary_reg(bbar, offset);
1112 start_bus = (
u8)((val & 0x00FF0000) >> 16);
1113 end_bus = (
u8)((val & 0x0000FF00) >> 8);
1116 for (bus = start_bus; bus <= end_bus; bus++) {
1122 bus_info[start_bus].
phbid = phb;
1131 for (bus = 0; bus <
ARRAY_SIZE(bus_info); bus++)
1132 if (bus_info[bus].bbar)
1138 static int __init calgary_init(
void)
1144 ret = calgary_locate_bbars();
1149 if (is_kdump_kernel())
1150 get_tce_space_from_tar();
1156 if (!is_cal_pci_dev(dev->
device))
1159 info = &bus_info[dev->
bus->number];
1161 calgary_init_one_nontraslated(dev);
1165 if (!info->
tce_space && !translate_empty_slots)
1168 ret = calgary_init_one(dev);
1177 tbl = find_iommu_table(&dev->
dev);
1179 if (translation_enabled(tbl))
1180 dev->
dev.archdata.dma_ops = &calgary_dma_ops;
1190 if (!is_cal_pci_dev(dev->
device))
1193 info = &bus_info[dev->
bus->number];
1198 if (!info->
tce_space && !translate_empty_slots)
1201 calgary_disable_translation(dev);
1202 calgary_free_bus(dev);
1204 dev->
dev.archdata.dma_ops =
NULL;
1210 static inline int __init determine_tce_table_size(
u64 ram)
1231 static int __init build_detail_arrays(
void)
1234 unsigned numnodes,
i;
1235 int scal_detail_size, rio_detail_size;
1240 "Calgary: MAX_NUMNODES too low! Defined as %d, "
1241 "but system has %d nodes.\n",
1248 scal_detail_size = 11;
1249 rio_detail_size = 13;
1252 scal_detail_size = 12;
1253 rio_detail_size = 15;
1257 "Calgary: Invalid Rio Grande Table Version: %d\n",
1263 for (i = 0; i < numnodes; i++, ptr += scal_detail_size)
1267 i++, ptr += rio_detail_size)
1273 static int __init calgary_bus_has_devices(
int bus,
unsigned short pci_dev)
1286 for (dev = 1; dev < 8; dev++) {
1288 if (val != 0xffffffff)
1291 return (val != 0xffffffff);
1299 static void calgary_init_bitmap_from_tce_table(
struct iommu_table *tbl)
1304 for (index = 0 ; index < tbl->
it_size; index++) {
1316 static void __init get_tce_space_from_tar(
void)
1320 unsigned long tce_space;
1328 pci_device = (val & 0xFFFF0000) >> 16;
1330 if (!is_cal_pci_dev(pci_device))
1335 if (calgary_bus_has_devices(bus, pci_device) ||
1336 translate_empty_slots) {
1337 target = calgary_reg(bus_info[bus].bbar,
1349 static int __init calgary_iommu_init(
void)
1356 ret = calgary_init();
1359 "falling back to no_iommu\n", ret);
1370 int calgary_found = 0;
1372 unsigned int offset, prev_offset;
1399 while (offset > prev_offset) {
1401 if (*((
unsigned short *)(ptr + offset + 2)) == 0x4752){
1407 offset = *((
unsigned short *)(ptr + offset));
1411 "in EBDA - bailing!\n");
1415 ret = build_detail_arrays();
1430 pci_device = (val & 0xFFFF0000) >> 16;
1432 if (!is_cal_pci_dev(pci_device))
1438 if (calgary_bus_has_devices(bus, pci_device) ||
1439 translate_empty_slots) {
1444 if (!is_kdump_kernel()) {
1455 calgary_found ?
"found" :
"not found");
1457 if (calgary_found) {
1459 calgary_detected = 1;
1464 x86_init.iommu.iommu_init = calgary_iommu_init;
1466 return calgary_found;
1469 for (--bus; bus >= 0; --
bus) {
1478 static int __init calgary_parse_options(
char *
p)
1488 else if (!
strncmp(p,
"128k", 4))
1490 else if (!
strncmp(p,
"256k", 4))
1492 else if (!
strncmp(p,
"512k", 4))
1494 else if (!
strncmp(p,
"1M", 2))
1496 else if (!
strncmp(p,
"2M", 2))
1498 else if (!
strncmp(p,
"4M", 2))
1500 else if (!
strncmp(p,
"8M", 2))
1503 len =
strlen(
"translate_empty_slots");
1504 if (!
strncmp(p,
"translate_empty_slots", len))
1505 translate_empty_slots = 1;
1508 if (!
strncmp(p,
"disable", len)) {
1514 ret = kstrtoul(p, 0, &val);
1519 if (bridge < MAX_PHB_BUS_NUM) {
1521 "translation for PHB %#x\n", bridge);
1534 __setup(
"calgary=", calgary_parse_options);
1536 static void __init calgary_fixup_one_tce_space(
struct pci_dev *dev)
1539 unsigned int npages;
1542 tbl = pci_iommu(dev->
bus);
1544 for (i = 0; i < 4; i++) {
1559 iommu_range_reserve(tbl, r->
start, npages);
1563 static int __init calgary_fixup_tce_spaces(
void)
1565 struct pci_dev *dev =
NULL;
1568 if (no_iommu ||
swiotlb || !calgary_detected)
1577 if (!is_cal_pci_dev(dev->
device))
1580 info = &bus_info[dev->
bus->number];
1587 calgary_fixup_one_tce_space(dev);