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.c36
1 files changed, 24 insertions, 12 deletions
diff --git a/arch/x86_64/kernel/pci-calgary.c b/arch/x86_64/kernel/pci-calgary.c
index f760045d6d35..b3296cc2f2f2 100644
--- a/arch/x86_64/kernel/pci-calgary.c
+++ b/arch/x86_64/kernel/pci-calgary.c
@@ -2,8 +2,9 @@
2 * Derived from arch/powerpc/kernel/iommu.c 2 * Derived from arch/powerpc/kernel/iommu.c
3 * 3 *
4 * Copyright (C) IBM Corporation, 2006 4 * Copyright (C) IBM Corporation, 2006
5 * Copyright (C) 2006 Jon Mason <jdmason@kudzu.us>
5 * 6 *
6 * Author: Jon Mason <jdmason@us.ibm.com> 7 * Author: Jon Mason <jdmason@kudzu.us>
7 * Author: Muli Ben-Yehuda <muli@il.ibm.com> 8 * Author: Muli Ben-Yehuda <muli@il.ibm.com>
8 9
9 * This program is free software; you can redistribute it and/or modify 10 * This program is free software; you can redistribute it and/or modify
@@ -714,7 +715,7 @@ static void calgary_watchdog(unsigned long data)
714 715
715 /* If no error, the agent ID in the CSR is not valid */ 716 /* If no error, the agent ID in the CSR is not valid */
716 if (val32 & CSR_AGENT_MASK) { 717 if (val32 & CSR_AGENT_MASK) {
717 printk(KERN_EMERG "calgary_watchdog: DMA error on bus %d, " 718 printk(KERN_EMERG "calgary_watchdog: DMA error on PHB %#x, "
718 "CSR = %#x\n", dev->bus->number, val32); 719 "CSR = %#x\n", dev->bus->number, val32);
719 writel(0, target); 720 writel(0, target);
720 721
@@ -748,7 +749,7 @@ static void __init calgary_enable_translation(struct pci_dev *dev)
748 val32 = be32_to_cpu(readl(target)); 749 val32 = be32_to_cpu(readl(target));
749 val32 |= PHB_TCE_ENABLE | PHB_DAC_DISABLE | PHB_MCSR_ENABLE; 750 val32 |= PHB_TCE_ENABLE | PHB_DAC_DISABLE | PHB_MCSR_ENABLE;
750 751
751 printk(KERN_INFO "Calgary: enabling translation on PHB %d\n", busnum); 752 printk(KERN_INFO "Calgary: enabling translation on PHB %#x\n", busnum);
752 printk(KERN_INFO "Calgary: errant DMAs will now be prevented on this " 753 printk(KERN_INFO "Calgary: errant DMAs will now be prevented on this "
753 "bus.\n"); 754 "bus.\n");
754 755
@@ -778,7 +779,7 @@ static void __init calgary_disable_translation(struct pci_dev *dev)
778 val32 = be32_to_cpu(readl(target)); 779 val32 = be32_to_cpu(readl(target));
779 val32 &= ~(PHB_TCE_ENABLE | PHB_DAC_DISABLE | PHB_MCSR_ENABLE); 780 val32 &= ~(PHB_TCE_ENABLE | PHB_DAC_DISABLE | PHB_MCSR_ENABLE);
780 781
781 printk(KERN_INFO "Calgary: disabling translation on PHB %d!\n", busnum); 782 printk(KERN_INFO "Calgary: disabling translation on PHB %#x!\n", busnum);
782 writel(cpu_to_be32(val32), target); 783 writel(cpu_to_be32(val32), target);
783 readl(target); /* flush */ 784 readl(target); /* flush */
784 785
@@ -790,7 +791,16 @@ static inline unsigned int __init locate_register_space(struct pci_dev *dev)
790 int rionodeid; 791 int rionodeid;
791 u32 address; 792 u32 address;
792 793
793 rionodeid = (dev->bus->number % 15 > 4) ? 3 : 2; 794 /*
795 * Each Calgary has four busses. The first four busses (first Calgary)
796 * have RIO node ID 2, then the next four (second Calgary) have RIO
797 * node ID 3, the next four (third Calgary) have node ID 2 again, etc.
798 * We use a gross hack - relying on the dev->bus->number ordering,
799 * modulo 14 - to decide which Calgary a given bus is on. Busses 0, 1,
800 * 2 and 4 are on the first Calgary (id 2), 6, 8, a and c are on the
801 * second (id 3), and then it repeats modulo 14.
802 */
803 rionodeid = (dev->bus->number % 14 > 4) ? 3 : 2;
794 /* 804 /*
795 * register space address calculation as follows: 805 * register space address calculation as follows:
796 * FE0MB-8MB*OneBasedChassisNumber+1MB*(RioNodeId-ChassisBase) 806 * FE0MB-8MB*OneBasedChassisNumber+1MB*(RioNodeId-ChassisBase)
@@ -798,7 +808,7 @@ static inline unsigned int __init locate_register_space(struct pci_dev *dev)
798 * RioNodeId is 2 for first Calgary, 3 for second Calgary 808 * RioNodeId is 2 for first Calgary, 3 for second Calgary
799 */ 809 */
800 address = START_ADDRESS - 810 address = START_ADDRESS -
801 (0x800000 * (ONE_BASED_CHASSIS_NUM + dev->bus->number / 15)) + 811 (0x800000 * (ONE_BASED_CHASSIS_NUM + dev->bus->number / 14)) +
802 (0x100000) * (rionodeid - CHASSIS_BASE); 812 (0x100000) * (rionodeid - CHASSIS_BASE);
803 return address; 813 return address;
804} 814}
@@ -816,6 +826,8 @@ static int __init calgary_init_one(struct pci_dev *dev)
816 void __iomem *bbar; 826 void __iomem *bbar;
817 int ret; 827 int ret;
818 828
829 BUG_ON(dev->bus->number >= MAX_PHB_BUS_NUM);
830
819 address = locate_register_space(dev); 831 address = locate_register_space(dev);
820 /* map entire 1MB of Calgary config space */ 832 /* map entire 1MB of Calgary config space */
821 bbar = ioremap_nocache(address, 1024 * 1024); 833 bbar = ioremap_nocache(address, 1024 * 1024);
@@ -842,10 +854,10 @@ done:
842 854
843static int __init calgary_init(void) 855static int __init calgary_init(void)
844{ 856{
845 int i, ret = -ENODEV; 857 int ret = -ENODEV;
846 struct pci_dev *dev = NULL; 858 struct pci_dev *dev = NULL;
847 859
848 for (i = 0; i < MAX_PHB_BUS_NUM; i++) { 860 do {
849 dev = pci_get_device(PCI_VENDOR_ID_IBM, 861 dev = pci_get_device(PCI_VENDOR_ID_IBM,
850 PCI_DEVICE_ID_IBM_CALGARY, 862 PCI_DEVICE_ID_IBM_CALGARY,
851 dev); 863 dev);
@@ -861,12 +873,12 @@ static int __init calgary_init(void)
861 ret = calgary_init_one(dev); 873 ret = calgary_init_one(dev);
862 if (ret) 874 if (ret)
863 goto error; 875 goto error;
864 } 876 } while (1);
865 877
866 return ret; 878 return ret;
867 879
868error: 880error:
869 for (i--; i >= 0; i--) { 881 do {
870 dev = pci_find_device_reverse(PCI_VENDOR_ID_IBM, 882 dev = pci_find_device_reverse(PCI_VENDOR_ID_IBM,
871 PCI_DEVICE_ID_IBM_CALGARY, 883 PCI_DEVICE_ID_IBM_CALGARY,
872 dev); 884 dev);
@@ -882,7 +894,7 @@ error:
882 calgary_disable_translation(dev); 894 calgary_disable_translation(dev);
883 calgary_free_bus(dev); 895 calgary_free_bus(dev);
884 pci_dev_put(dev); /* Undo calgary_init_one()'s pci_dev_get() */ 896 pci_dev_put(dev); /* Undo calgary_init_one()'s pci_dev_get() */
885 } 897 } while (1);
886 898
887 return ret; 899 return ret;
888} 900}
@@ -1052,7 +1064,7 @@ static int __init calgary_parse_options(char *p)
1052 1064
1053 if (bridge < MAX_PHB_BUS_NUM) { 1065 if (bridge < MAX_PHB_BUS_NUM) {
1054 printk(KERN_INFO "Calgary: disabling " 1066 printk(KERN_INFO "Calgary: disabling "
1055 "translation for PHB 0x%x\n", bridge); 1067 "translation for PHB %#x\n", bridge);
1056 bus_info[bridge].translation_disabled = 1; 1068 bus_info[bridge].translation_disabled = 1;
1057 } 1069 }
1058 } 1070 }