aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86_64/kernel/pci-calgary.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86_64/kernel/pci-calgary.c')
-rw-r--r--arch/x86_64/kernel/pci-calgary.c142
1 files changed, 90 insertions, 52 deletions
diff --git a/arch/x86_64/kernel/pci-calgary.c b/arch/x86_64/kernel/pci-calgary.c
index 146924ba5df5..cfb09b07ae99 100644
--- a/arch/x86_64/kernel/pci-calgary.c
+++ b/arch/x86_64/kernel/pci-calgary.c
@@ -86,7 +86,8 @@
86 86
87#define MAX_NUM_OF_PHBS 8 /* how many PHBs in total? */ 87#define MAX_NUM_OF_PHBS 8 /* how many PHBs in total? */
88#define MAX_NUM_CHASSIS 8 /* max number of chassis */ 88#define MAX_NUM_CHASSIS 8 /* max number of chassis */
89#define MAX_PHB_BUS_NUM (MAX_NUM_OF_PHBS * MAX_NUM_CHASSIS * 2) /* max dev->bus->number */ 89/* MAX_PHB_BUS_NUM is the maximal possible dev->bus->number */
90#define MAX_PHB_BUS_NUM (MAX_NUM_OF_PHBS * MAX_NUM_CHASSIS * 2)
90#define PHBS_PER_CALGARY 4 91#define PHBS_PER_CALGARY 4
91 92
92/* register offsets in Calgary's internal register space */ 93/* register offsets in Calgary's internal register space */
@@ -111,31 +112,49 @@ static const unsigned long phb_offsets[] = {
111 0xB000 /* PHB3 */ 112 0xB000 /* PHB3 */
112}; 113};
113 114
114static char bus_to_phb[MAX_PHB_BUS_NUM];
115void* tce_table_kva[MAX_PHB_BUS_NUM];
116unsigned int specified_table_size = TCE_TABLE_SIZE_UNSPECIFIED; 115unsigned int specified_table_size = TCE_TABLE_SIZE_UNSPECIFIED;
117static int translate_empty_slots __read_mostly = 0; 116static int translate_empty_slots __read_mostly = 0;
118static int calgary_detected __read_mostly = 0; 117static int calgary_detected __read_mostly = 0;
119 118
120/* 119struct calgary_bus_info {
121 * the bitmap of PHBs the user requested that we disable 120 void *tce_space;
122 * translation on. 121 unsigned char translation_disabled;
123 */ 122 signed char phbid;
124static DECLARE_BITMAP(translation_disabled, MAX_PHB_BUS_NUM); 123};
124
125static struct calgary_bus_info bus_info[MAX_PHB_BUS_NUM] = { { NULL, 0, 0 }, };
125 126
126static void tce_cache_blast(struct iommu_table *tbl); 127static void tce_cache_blast(struct iommu_table *tbl);
127 128
128/* enable this to stress test the chip's TCE cache */ 129/* enable this to stress test the chip's TCE cache */
129#ifdef CONFIG_IOMMU_DEBUG 130#ifdef CONFIG_IOMMU_DEBUG
130static inline void tce_cache_blast_stress(struct iommu_table *tbl) 131int debugging __read_mostly = 1;
132
133static inline unsigned long verify_bit_range(unsigned long* bitmap,
134 int expected, unsigned long start, unsigned long end)
131{ 135{
132 tce_cache_blast(tbl); 136 unsigned long idx = start;
137
138 BUG_ON(start >= end);
139
140 while (idx < end) {
141 if (!!test_bit(idx, bitmap) != expected)
142 return idx;
143 ++idx;
144 }
145
146 /* all bits have the expected value */
147 return ~0UL;
133} 148}
134#else 149#else /* debugging is disabled */
135static inline void tce_cache_blast_stress(struct iommu_table *tbl) 150int debugging __read_mostly = 0;
151
152static inline unsigned long verify_bit_range(unsigned long* bitmap,
153 int expected, unsigned long start, unsigned long end)
136{ 154{
155 return ~0UL;
137} 156}
138#endif /* BLAST_TCE_CACHE_ON_UNMAP */ 157#endif /* CONFIG_IOMMU_DEBUG */
139 158
140static inline unsigned int num_dma_pages(unsigned long dma, unsigned int dmalen) 159static inline unsigned int num_dma_pages(unsigned long dma, unsigned int dmalen)
141{ 160{
@@ -149,7 +168,7 @@ static inline unsigned int num_dma_pages(unsigned long dma, unsigned int dmalen)
149 168
150static inline int translate_phb(struct pci_dev* dev) 169static inline int translate_phb(struct pci_dev* dev)
151{ 170{
152 int disabled = test_bit(dev->bus->number, translation_disabled); 171 int disabled = bus_info[dev->bus->number].translation_disabled;
153 return !disabled; 172 return !disabled;
154} 173}
155 174
@@ -158,6 +177,7 @@ static void iommu_range_reserve(struct iommu_table *tbl,
158{ 177{
159 unsigned long index; 178 unsigned long index;
160 unsigned long end; 179 unsigned long end;
180 unsigned long badbit;
161 181
162 index = start_addr >> PAGE_SHIFT; 182 index = start_addr >> PAGE_SHIFT;
163 183
@@ -169,14 +189,15 @@ static void iommu_range_reserve(struct iommu_table *tbl,
169 if (end > tbl->it_size) /* don't go off the table */ 189 if (end > tbl->it_size) /* don't go off the table */
170 end = tbl->it_size; 190 end = tbl->it_size;
171 191
172 while (index < end) { 192 badbit = verify_bit_range(tbl->it_map, 0, index, end);
173 if (test_bit(index, tbl->it_map)) 193 if (badbit != ~0UL) {
194 if (printk_ratelimit())
174 printk(KERN_ERR "Calgary: entry already allocated at " 195 printk(KERN_ERR "Calgary: entry already allocated at "
175 "0x%lx tbl %p dma 0x%lx npages %u\n", 196 "0x%lx tbl %p dma 0x%lx npages %u\n",
176 index, tbl, start_addr, npages); 197 badbit, tbl, start_addr, npages);
177 ++index;
178 } 198 }
179 set_bit_string(tbl->it_map, start_addr >> PAGE_SHIFT, npages); 199
200 set_bit_string(tbl->it_map, index, npages);
180} 201}
181 202
182static unsigned long iommu_range_alloc(struct iommu_table *tbl, 203static unsigned long iommu_range_alloc(struct iommu_table *tbl,
@@ -243,7 +264,7 @@ static void __iommu_free(struct iommu_table *tbl, dma_addr_t dma_addr,
243 unsigned int npages) 264 unsigned int npages)
244{ 265{
245 unsigned long entry; 266 unsigned long entry;
246 unsigned long i; 267 unsigned long badbit;
247 268
248 entry = dma_addr >> PAGE_SHIFT; 269 entry = dma_addr >> PAGE_SHIFT;
249 270
@@ -251,16 +272,15 @@ static void __iommu_free(struct iommu_table *tbl, dma_addr_t dma_addr,
251 272
252 tce_free(tbl, entry, npages); 273 tce_free(tbl, entry, npages);
253 274
254 for (i = 0; i < npages; ++i) { 275 badbit = verify_bit_range(tbl->it_map, 1, entry, entry + npages);
255 if (!test_bit(entry + i, tbl->it_map)) 276 if (badbit != ~0UL) {
277 if (printk_ratelimit())
256 printk(KERN_ERR "Calgary: bit is off at 0x%lx " 278 printk(KERN_ERR "Calgary: bit is off at 0x%lx "
257 "tbl %p dma 0x%Lx entry 0x%lx npages %u\n", 279 "tbl %p dma 0x%Lx entry 0x%lx npages %u\n",
258 entry + i, tbl, dma_addr, entry, npages); 280 badbit, tbl, dma_addr, entry, npages);
259 } 281 }
260 282
261 __clear_bit_string(tbl->it_map, entry, npages); 283 __clear_bit_string(tbl->it_map, entry, npages);
262
263 tce_cache_blast_stress(tbl);
264} 284}
265 285
266static void iommu_free(struct iommu_table *tbl, dma_addr_t dma_addr, 286static void iommu_free(struct iommu_table *tbl, dma_addr_t dma_addr,
@@ -454,7 +474,7 @@ static struct dma_mapping_ops calgary_dma_ops = {
454 474
455static inline int busno_to_phbid(unsigned char num) 475static inline int busno_to_phbid(unsigned char num)
456{ 476{
457 return bus_to_phb[num]; 477 return bus_info[num].phbid;
458} 478}
459 479
460static inline unsigned long split_queue_offset(unsigned char num) 480static inline unsigned long split_queue_offset(unsigned char num)
@@ -631,6 +651,10 @@ static int __init calgary_setup_tar(struct pci_dev *dev, void __iomem *bbar)
631 if (ret) 651 if (ret)
632 return ret; 652 return ret;
633 653
654 tbl = dev->sysdata;
655 tbl->it_base = (unsigned long)bus_info[dev->bus->number].tce_space;
656 tce_free(tbl, 0, tbl->it_size);
657
634 calgary_reserve_regions(dev); 658 calgary_reserve_regions(dev);
635 659
636 /* set TARs for each PHB */ 660 /* set TARs for each PHB */
@@ -654,11 +678,12 @@ static int __init calgary_setup_tar(struct pci_dev *dev, void __iomem *bbar)
654 return 0; 678 return 0;
655} 679}
656 680
657static void __init calgary_free_tar(struct pci_dev *dev) 681static void __init calgary_free_bus(struct pci_dev *dev)
658{ 682{
659 u64 val64; 683 u64 val64;
660 struct iommu_table *tbl = dev->sysdata; 684 struct iommu_table *tbl = dev->sysdata;
661 void __iomem *target; 685 void __iomem *target;
686 unsigned int bitmapsz;
662 687
663 target = calgary_reg(tbl->bbar, tar_offset(dev->bus->number)); 688 target = calgary_reg(tbl->bbar, tar_offset(dev->bus->number));
664 val64 = be64_to_cpu(readq(target)); 689 val64 = be64_to_cpu(readq(target));
@@ -666,8 +691,15 @@ static void __init calgary_free_tar(struct pci_dev *dev)
666 writeq(cpu_to_be64(val64), target); 691 writeq(cpu_to_be64(val64), target);
667 readq(target); /* flush */ 692 readq(target); /* flush */
668 693
694 bitmapsz = tbl->it_size / BITS_PER_BYTE;
695 free_pages((unsigned long)tbl->it_map, get_order(bitmapsz));
696 tbl->it_map = NULL;
697
669 kfree(tbl); 698 kfree(tbl);
670 dev->sysdata = NULL; 699 dev->sysdata = NULL;
700
701 /* Can't free bootmem allocated memory after system is up :-( */
702 bus_info[dev->bus->number].tce_space = NULL;
671} 703}
672 704
673static void calgary_watchdog(unsigned long data) 705static void calgary_watchdog(unsigned long data)
@@ -772,12 +804,11 @@ static inline unsigned int __init locate_register_space(struct pci_dev *dev)
772 return address; 804 return address;
773} 805}
774 806
775static int __init calgary_init_one_nontraslated(struct pci_dev *dev) 807static void __init calgary_init_one_nontraslated(struct pci_dev *dev)
776{ 808{
809 pci_dev_get(dev);
777 dev->sysdata = NULL; 810 dev->sysdata = NULL;
778 dev->bus->self = dev; 811 dev->bus->self = dev;
779
780 return 0;
781} 812}
782 813
783static int __init calgary_init_one(struct pci_dev *dev) 814static int __init calgary_init_one(struct pci_dev *dev)
@@ -798,6 +829,7 @@ static int __init calgary_init_one(struct pci_dev *dev)
798 if (ret) 829 if (ret)
799 goto iounmap; 830 goto iounmap;
800 831
832 pci_dev_get(dev);
801 dev->bus->self = dev; 833 dev->bus->self = dev;
802 calgary_enable_translation(dev); 834 calgary_enable_translation(dev);
803 835
@@ -824,10 +856,9 @@ static int __init calgary_init(void)
824 calgary_init_one_nontraslated(dev); 856 calgary_init_one_nontraslated(dev);
825 continue; 857 continue;
826 } 858 }
827 if (!tce_table_kva[dev->bus->number] && !translate_empty_slots) { 859 if (!bus_info[dev->bus->number].tce_space && !translate_empty_slots)
828 pci_dev_put(dev);
829 continue; 860 continue;
830 } 861
831 ret = calgary_init_one(dev); 862 ret = calgary_init_one(dev);
832 if (ret) 863 if (ret)
833 goto error; 864 goto error;
@@ -840,15 +871,18 @@ error:
840 dev = pci_find_device_reverse(PCI_VENDOR_ID_IBM, 871 dev = pci_find_device_reverse(PCI_VENDOR_ID_IBM,
841 PCI_DEVICE_ID_IBM_CALGARY, 872 PCI_DEVICE_ID_IBM_CALGARY,
842 dev); 873 dev);
874 if (!dev)
875 break;
843 if (!translate_phb(dev)) { 876 if (!translate_phb(dev)) {
844 pci_dev_put(dev); 877 pci_dev_put(dev);
845 continue; 878 continue;
846 } 879 }
847 if (!tce_table_kva[dev->bus->number] && !translate_empty_slots) 880 if (!bus_info[dev->bus->number].tce_space && !translate_empty_slots)
848 continue; 881 continue;
882
849 calgary_disable_translation(dev); 883 calgary_disable_translation(dev);
850 calgary_free_tar(dev); 884 calgary_free_bus(dev);
851 pci_dev_put(dev); 885 pci_dev_put(dev); /* Undo calgary_init_one()'s pci_dev_get() */
852 } 886 }
853 887
854 return ret; 888 return ret;
@@ -890,13 +924,15 @@ void __init detect_calgary(void)
890 if (swiotlb || no_iommu || iommu_detected) 924 if (swiotlb || no_iommu || iommu_detected)
891 return; 925 return;
892 926
927 if (!early_pci_allowed())
928 return;
929
893 specified_table_size = determine_tce_table_size(end_pfn * PAGE_SIZE); 930 specified_table_size = determine_tce_table_size(end_pfn * PAGE_SIZE);
894 931
895 for (bus = 0; bus < MAX_PHB_BUS_NUM; bus++) { 932 for (bus = 0; bus < MAX_PHB_BUS_NUM; bus++) {
896 int dev; 933 int dev;
897 934 struct calgary_bus_info *info = &bus_info[bus];
898 tce_table_kva[bus] = NULL; 935 info->phbid = -1;
899 bus_to_phb[bus] = -1;
900 936
901 if (read_pci_config(bus, 0, 0, 0) != PCI_VENDOR_DEVICE_ID_CALGARY) 937 if (read_pci_config(bus, 0, 0, 0) != PCI_VENDOR_DEVICE_ID_CALGARY)
902 continue; 938 continue;
@@ -907,12 +943,9 @@ void __init detect_calgary(void)
907 */ 943 */
908 phb = (phb + 1) % PHBS_PER_CALGARY; 944 phb = (phb + 1) % PHBS_PER_CALGARY;
909 945
910 if (test_bit(bus, translation_disabled)) { 946 if (info->translation_disabled)
911 printk(KERN_INFO "Calgary: translation is disabled for "
912 "PHB 0x%x\n", bus);
913 /* skip this phb, don't allocate a tbl for it */
914 continue; 947 continue;
915 } 948
916 /* 949 /*
917 * Scan the slots of the PCI bus to see if there is a device present. 950 * Scan the slots of the PCI bus to see if there is a device present.
918 * The parent bus will be the zero-ith device, so start at 1. 951 * The parent bus will be the zero-ith device, so start at 1.
@@ -923,8 +956,8 @@ void __init detect_calgary(void)
923 tbl = alloc_tce_table(); 956 tbl = alloc_tce_table();
924 if (!tbl) 957 if (!tbl)
925 goto cleanup; 958 goto cleanup;
926 tce_table_kva[bus] = tbl; 959 info->tce_space = tbl;
927 bus_to_phb[bus] = phb; 960 info->phbid = phb;
928 calgary_found = 1; 961 calgary_found = 1;
929 break; 962 break;
930 } 963 }
@@ -934,15 +967,20 @@ void __init detect_calgary(void)
934 if (calgary_found) { 967 if (calgary_found) {
935 iommu_detected = 1; 968 iommu_detected = 1;
936 calgary_detected = 1; 969 calgary_detected = 1;
937 printk(KERN_INFO "PCI-DMA: Calgary IOMMU detected. " 970 printk(KERN_INFO "PCI-DMA: Calgary IOMMU detected.\n");
938 "TCE table spec is %d.\n", specified_table_size); 971 printk(KERN_INFO "PCI-DMA: Calgary TCE table spec is %d, "
972 "CONFIG_IOMMU_DEBUG is %s.\n", specified_table_size,
973 debugging ? "enabled" : "disabled");
939 } 974 }
940 return; 975 return;
941 976
942cleanup: 977cleanup:
943 for (--bus; bus >= 0; --bus) 978 for (--bus; bus >= 0; --bus) {
944 if (tce_table_kva[bus]) 979 struct calgary_bus_info *info = &bus_info[bus];
945 free_tce_table(tce_table_kva[bus]); 980
981 if (info->tce_space)
982 free_tce_table(info->tce_space);
983 }
946} 984}
947 985
948int __init calgary_iommu_init(void) 986int __init calgary_iommu_init(void)
@@ -1016,7 +1054,7 @@ static int __init calgary_parse_options(char *p)
1016 if (bridge < MAX_PHB_BUS_NUM) { 1054 if (bridge < MAX_PHB_BUS_NUM) {
1017 printk(KERN_INFO "Calgary: disabling " 1055 printk(KERN_INFO "Calgary: disabling "
1018 "translation for PHB 0x%x\n", bridge); 1056 "translation for PHB 0x%x\n", bridge);
1019 set_bit(bridge, translation_disabled); 1057 bus_info[bridge].translation_disabled = 1;
1020 } 1058 }
1021 } 1059 }
1022 1060