diff options
Diffstat (limited to 'arch/x86_64/kernel/pci-calgary.c')
| -rw-r--r-- | arch/x86_64/kernel/pci-calgary.c | 36 |
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 | ||
| 843 | static int __init calgary_init(void) | 855 | static 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 | ||
| 868 | error: | 880 | error: |
| 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 | } |
