aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorMuli Ben-Yehuda <muli@il.ibm.com>2007-07-21 11:10:54 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-07-21 21:37:11 -0400
commit00be3fa42f164f7e2783a5acf9766fb07fb64e68 (patch)
tree412ae20743aa65041367f521bd0c00ec0fad2a8e /arch
parentc38601084b386991f1614f03e0323c51236e19e1 (diff)
x86_64: implement CalIOC2 TCE cache flush sequence
Signed-off-by: Muli Ben-Yehuda <muli@il.ibm.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Andi Kleen <ak@suse.de> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'arch')
-rw-r--r--arch/x86_64/kernel/pci-calgary.c88
1 files changed, 87 insertions, 1 deletions
diff --git a/arch/x86_64/kernel/pci-calgary.c b/arch/x86_64/kernel/pci-calgary.c
index 68634f192de8..765c521dd85f 100644
--- a/arch/x86_64/kernel/pci-calgary.c
+++ b/arch/x86_64/kernel/pci-calgary.c
@@ -81,6 +81,8 @@ int use_calgary __read_mostly = 0;
81 81
82/* CalIOC2 specific */ 82/* CalIOC2 specific */
83#define PHB_SAVIOR_L2 0x0DB0 83#define PHB_SAVIOR_L2 0x0DB0
84#define PHB_PAGE_MIG_CTRL 0x0DA8
85#define PHB_PAGE_MIG_DEBUG 0x0DA0
84 86
85/* PHB_CONFIG_RW */ 87/* PHB_CONFIG_RW */
86#define PHB_TCE_ENABLE 0x20000000 88#define PHB_TCE_ENABLE 0x20000000
@@ -95,6 +97,10 @@ int use_calgary __read_mostly = 0;
95#define CSR_AGENT_MASK 0xffe0ffff 97#define CSR_AGENT_MASK 0xffe0ffff
96/* CCR (Calgary Configuration Register) */ 98/* CCR (Calgary Configuration Register) */
97#define CCR_2SEC_TIMEOUT 0x000000000000000EUL 99#define CCR_2SEC_TIMEOUT 0x000000000000000EUL
100/* PMCR/PMDR (Page Migration Control/Debug Registers */
101#define PMR_SOFTSTOP 0x80000000
102#define PMR_SOFTSTOPFAULT 0x40000000
103#define PMR_HARDSTOP 0x20000000
98 104
99#define MAX_NUM_OF_PHBS 8 /* how many PHBs in total? */ 105#define MAX_NUM_OF_PHBS 8 /* how many PHBs in total? */
100#define MAX_NUM_CHASSIS 8 /* max number of chassis */ 106#define MAX_NUM_CHASSIS 8 /* max number of chassis */
@@ -160,6 +166,7 @@ struct calgary_bus_info {
160static void calgary_handle_quirks(struct iommu_table *tbl, struct pci_dev *dev); 166static void calgary_handle_quirks(struct iommu_table *tbl, struct pci_dev *dev);
161static void calgary_tce_cache_blast(struct iommu_table *tbl); 167static void calgary_tce_cache_blast(struct iommu_table *tbl);
162static void calioc2_handle_quirks(struct iommu_table *tbl, struct pci_dev *dev); 168static void calioc2_handle_quirks(struct iommu_table *tbl, struct pci_dev *dev);
169static void calioc2_tce_cache_blast(struct iommu_table *tbl);
163 170
164static struct cal_chipset_ops calgary_chip_ops = { 171static struct cal_chipset_ops calgary_chip_ops = {
165 .handle_quirks = calgary_handle_quirks, 172 .handle_quirks = calgary_handle_quirks,
@@ -168,7 +175,7 @@ static struct cal_chipset_ops calgary_chip_ops = {
168 175
169static struct cal_chipset_ops calioc2_chip_ops = { 176static struct cal_chipset_ops calioc2_chip_ops = {
170 .handle_quirks = calioc2_handle_quirks, 177 .handle_quirks = calioc2_handle_quirks,
171 .tce_cache_blast = NULL 178 .tce_cache_blast = calioc2_tce_cache_blast
172}; 179};
173 180
174static struct calgary_bus_info bus_info[MAX_PHB_BUS_NUM] = { { NULL, 0, 0 }, }; 181static struct calgary_bus_info bus_info[MAX_PHB_BUS_NUM] = { { NULL, 0, 0 }, };
@@ -637,6 +644,85 @@ static void calgary_tce_cache_blast(struct iommu_table *tbl)
637 (void)readl(target); /* flush */ 644 (void)readl(target); /* flush */
638} 645}
639 646
647static void calioc2_tce_cache_blast(struct iommu_table *tbl)
648{
649 void __iomem *bbar = tbl->bbar;
650 void __iomem *target;
651 u64 val64;
652 u32 val;
653 int i = 0;
654 int count = 1;
655 unsigned char bus = tbl->it_busno;
656
657begin:
658 printk(KERN_DEBUG "Calgary: CalIOC2 bus 0x%x entering tce cache blast "
659 "sequence - count %d\n", bus, count);
660
661 /* 1. using the Page Migration Control reg set SoftStop */
662 target = calgary_reg(bbar, phb_offset(bus) | PHB_PAGE_MIG_CTRL);
663 val = be32_to_cpu(readl(target));
664 printk(KERN_DEBUG "1a. read 0x%x [LE] from %p\n", val, target);
665 val |= PMR_SOFTSTOP;
666 printk(KERN_DEBUG "1b. writing 0x%x [LE] to %p\n", val, target);
667 writel(cpu_to_be32(val), target);
668
669 /* 2. poll split queues until all DMA activity is done */
670 printk(KERN_DEBUG "2a. starting to poll split queues\n");
671 target = calgary_reg(bbar, split_queue_offset(bus));
672 do {
673 val64 = readq(target);
674 i++;
675 } while ((val64 & 0xff) != 0xff && i < 100);
676 if (i == 100)
677 printk(KERN_WARNING "CalIOC2: PCI bus not quiesced, "
678 "continuing anyway\n");
679
680 /* 3. poll Page Migration DEBUG for SoftStopFault */
681 target = calgary_reg(bbar, phb_offset(bus) | PHB_PAGE_MIG_DEBUG);
682 val = be32_to_cpu(readl(target));
683 printk(KERN_DEBUG "3. read 0x%x [LE] from %p\n", val, target);
684
685 /* 4. if SoftStopFault - goto (1) */
686 if (val & PMR_SOFTSTOPFAULT) {
687 if (++count < 100)
688 goto begin;
689 else {
690 printk(KERN_WARNING "CalIOC2: too many SoftStopFaults, "
691 "aborting TCE cache flush sequence!\n");
692 return; /* pray for the best */
693 }
694 }
695
696 /* 5. Slam into HardStop by reading PHB_PAGE_MIG_CTRL */
697 target = calgary_reg(bbar, phb_offset(bus) | PHB_PAGE_MIG_CTRL);
698 printk(KERN_DEBUG "5a. slamming into HardStop by reading %p\n", target);
699 val = be32_to_cpu(readl(target));
700 printk(KERN_DEBUG "5b. read 0x%x [LE] from %p\n", val, target);
701 target = calgary_reg(bbar, phb_offset(bus) | PHB_PAGE_MIG_DEBUG);
702 val = be32_to_cpu(readl(target));
703 printk(KERN_DEBUG "5c. read 0x%x [LE] from %p (debug)\n", val, target);
704
705 /* 6. invalidate TCE cache */
706 printk(KERN_DEBUG "6. invalidating TCE cache\n");
707 target = calgary_reg(bbar, tar_offset(bus));
708 writeq(tbl->tar_val, target);
709
710 /* 7. Re-read PMCR */
711 printk(KERN_DEBUG "7a. Re-reading PMCR\n");
712 target = calgary_reg(bbar, phb_offset(bus) | PHB_PAGE_MIG_CTRL);
713 val = be32_to_cpu(readl(target));
714 printk(KERN_DEBUG "7b. read 0x%x [LE] from %p\n", val, target);
715
716 /* 8. Remove HardStop */
717 printk(KERN_DEBUG "8a. removing HardStop from PMCR\n");
718 target = calgary_reg(bbar, phb_offset(bus) | PHB_PAGE_MIG_CTRL);
719 val = 0;
720 printk(KERN_DEBUG "8b. writing 0x%x [LE] to %p\n", val, target);
721 writel(cpu_to_be32(val), target);
722 val = be32_to_cpu(readl(target));
723 printk(KERN_DEBUG "8c. read 0x%x [LE] from %p\n", val, target);
724}
725
640static void __init calgary_reserve_mem_region(struct pci_dev *dev, u64 start, 726static void __init calgary_reserve_mem_region(struct pci_dev *dev, u64 start,
641 u64 limit) 727 u64 limit)
642{ 728{