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.c85
1 files changed, 49 insertions, 36 deletions
diff --git a/arch/x86_64/kernel/pci-calgary.c b/arch/x86_64/kernel/pci-calgary.c
index afc0a53505f1..8a1e4f35bc3c 100644
--- a/arch/x86_64/kernel/pci-calgary.c
+++ b/arch/x86_64/kernel/pci-calgary.c
@@ -138,7 +138,7 @@ static int calgary_detected __read_mostly = 0;
138 138
139static struct rio_table_hdr *rio_table_hdr __initdata; 139static struct rio_table_hdr *rio_table_hdr __initdata;
140static struct scal_detail *scal_devs[MAX_NUMNODES] __initdata; 140static struct scal_detail *scal_devs[MAX_NUMNODES] __initdata;
141static struct rio_detail *rio_devs[MAX_NUMNODES*4] __initdata; 141static struct rio_detail *rio_devs[MAX_NUMNODES * 4] __initdata;
142 142
143struct calgary_bus_info { 143struct calgary_bus_info {
144 void *tce_space; 144 void *tce_space;
@@ -855,11 +855,6 @@ static void __init calgary_disable_translation(struct pci_dev *dev)
855 del_timer_sync(&tbl->watchdog_timer); 855 del_timer_sync(&tbl->watchdog_timer);
856} 856}
857 857
858static inline void __iomem * __init locate_register_space(struct pci_dev *dev)
859{
860 return busno_to_bbar(dev->bus->number);
861}
862
863static void __init calgary_init_one_nontraslated(struct pci_dev *dev) 858static void __init calgary_init_one_nontraslated(struct pci_dev *dev)
864{ 859{
865 pci_dev_get(dev); 860 pci_dev_get(dev);
@@ -874,15 +869,10 @@ static int __init calgary_init_one(struct pci_dev *dev)
874 869
875 BUG_ON(dev->bus->number >= MAX_PHB_BUS_NUM); 870 BUG_ON(dev->bus->number >= MAX_PHB_BUS_NUM);
876 871
877 bbar = locate_register_space(dev); 872 bbar = busno_to_bbar(dev->bus->number);
878 if (!bbar) {
879 ret = -ENODATA;
880 goto done;
881 }
882
883 ret = calgary_setup_tar(dev, bbar); 873 ret = calgary_setup_tar(dev, bbar);
884 if (ret) 874 if (ret)
885 goto iounmap; 875 goto done;
886 876
887 pci_dev_get(dev); 877 pci_dev_get(dev);
888 dev->bus->self = dev; 878 dev->bus->self = dev;
@@ -890,38 +880,39 @@ static int __init calgary_init_one(struct pci_dev *dev)
890 880
891 return 0; 881 return 0;
892 882
893iounmap:
894 iounmap(bbar);
895done: 883done:
896 return ret; 884 return ret;
897} 885}
898 886
899static int __init calgary_init(void) 887static int __init calgary_locate_bbars(void)
900{ 888{
901 int ret = -ENODEV; 889 int ret;
902 struct pci_dev *dev = NULL; 890 int rioidx, phb, bus;
903 int rio, phb, bus;
904 void __iomem *bbar; 891 void __iomem *bbar;
905 void __iomem *target; 892 void __iomem *target;
893 unsigned long offset;
906 u8 start_bus, end_bus; 894 u8 start_bus, end_bus;
907 u32 val; 895 u32 val;
908 896
909 for (rio = 0; rio < rio_table_hdr->num_rio_dev; rio++) { 897 ret = -ENODATA;
898 for (rioidx = 0; rioidx < rio_table_hdr->num_rio_dev; rioidx++) {
899 struct rio_detail *rio = rio_devs[rioidx];
910 900
911 if ( (rio_devs[rio]->type != COMPAT_CALGARY) && 901 if ((rio->type != COMPAT_CALGARY) && (rio->type != ALT_CALGARY))
912 (rio_devs[rio]->type != ALT_CALGARY) )
913 continue; 902 continue;
914 903
915 /* map entire 1MB of Calgary config space */ 904 /* map entire 1MB of Calgary config space */
916 bbar = ioremap_nocache(rio_devs[rio]->BBAR, 1024 * 1024); 905 bbar = ioremap_nocache(rio->BBAR, 1024 * 1024);
906 if (!bbar)
907 goto error;
917 908
918 for (phb = 0; phb < PHBS_PER_CALGARY; phb++) { 909 for (phb = 0; phb < PHBS_PER_CALGARY; phb++) {
910 offset = phb_debug_offsets[phb] | PHB_DEBUG_STUFF_OFFSET;
911 target = calgary_reg(bbar, offset);
919 912
920 target = calgary_reg(bbar, phb_debug_offsets[phb] |
921 PHB_DEBUG_STUFF_OFFSET);
922 val = be32_to_cpu(readl(target)); 913 val = be32_to_cpu(readl(target));
923 start_bus = (u8)((val & 0x00FF0000) >> 16); 914 start_bus = (u8)((val & 0x00FF0000) >> 16);
924 end_bus = (u8)((val & 0x0000FF00) >> 8); 915 end_bus = (u8)((val & 0x0000FF00) >> 8);
925 for (bus = start_bus; bus <= end_bus; bus++) { 916 for (bus = start_bus; bus <= end_bus; bus++) {
926 bus_info[bus].bbar = bbar; 917 bus_info[bus].bbar = bbar;
927 bus_info[bus].phbid = phb; 918 bus_info[bus].phbid = phb;
@@ -929,6 +920,25 @@ static int __init calgary_init(void)
929 } 920 }
930 } 921 }
931 922
923 return 0;
924
925error:
926 /* scan bus_info and iounmap any bbars we previously ioremap'd */
927 for (bus = 0; bus < ARRAY_SIZE(bus_info); bus++)
928 if (bus_info[bus].bbar)
929 iounmap(bus_info[bus].bbar);
930
931 return ret;
932}
933
934static int __init calgary_init(void)
935{
936 int ret;
937 struct pci_dev *dev = NULL;
938
939 ret = calgary_locate_bbars();
940 if (ret)
941 return ret;
932 942
933 do { 943 do {
934 dev = pci_get_device(PCI_VENDOR_ID_IBM, 944 dev = pci_get_device(PCI_VENDOR_ID_IBM,
@@ -1000,18 +1010,13 @@ static int __init build_detail_arrays(void)
1000 1010
1001 if (rio_table_hdr->num_scal_dev > MAX_NUMNODES){ 1011 if (rio_table_hdr->num_scal_dev > MAX_NUMNODES){
1002 printk(KERN_WARNING 1012 printk(KERN_WARNING
1003 "Calgary: MAX_NUMNODES too low! Defined as %d, " 1013 "Calgary: MAX_NUMNODES too low! Defined as %d, "
1004 "but system has %d nodes.\n", 1014 "but system has %d nodes.\n",
1005 MAX_NUMNODES, rio_table_hdr->num_scal_dev); 1015 MAX_NUMNODES, rio_table_hdr->num_scal_dev);
1006 return -ENODEV; 1016 return -ENODEV;
1007 } 1017 }
1008 1018
1009 switch (rio_table_hdr->version){ 1019 switch (rio_table_hdr->version){
1010 default:
1011 printk(KERN_WARNING
1012 "Calgary: Invalid Rio Grande Table Version: %d\n",
1013 rio_table_hdr->version);
1014 return -ENODEV;
1015 case 2: 1020 case 2:
1016 scal_detail_size = 11; 1021 scal_detail_size = 11;
1017 rio_detail_size = 13; 1022 rio_detail_size = 13;
@@ -1020,6 +1025,11 @@ static int __init build_detail_arrays(void)
1020 scal_detail_size = 12; 1025 scal_detail_size = 12;
1021 rio_detail_size = 15; 1026 rio_detail_size = 15;
1022 break; 1027 break;
1028 default:
1029 printk(KERN_WARNING
1030 "Calgary: Invalid Rio Grande Table Version: %d\n",
1031 rio_table_hdr->version);
1032 return -EPROTO;
1023 } 1033 }
1024 1034
1025 ptr = ((unsigned long)rio_table_hdr) + 3; 1035 ptr = ((unsigned long)rio_table_hdr) + 3;
@@ -1042,6 +1052,7 @@ void __init detect_calgary(void)
1042 int calgary_found = 0; 1052 int calgary_found = 0;
1043 unsigned long ptr; 1053 unsigned long ptr;
1044 int offset; 1054 int offset;
1055 int ret;
1045 1056
1046 /* 1057 /*
1047 * if the user specified iommu=off or iommu=soft or we found 1058 * if the user specified iommu=off or iommu=soft or we found
@@ -1061,27 +1072,29 @@ void __init detect_calgary(void)
1061 /* The block id is stored in the 2nd word */ 1072 /* The block id is stored in the 2nd word */
1062 if (*((unsigned short *)(ptr + offset + 2)) == 0x4752){ 1073 if (*((unsigned short *)(ptr + offset + 2)) == 0x4752){
1063 /* set the pointer past the offset & block id */ 1074 /* set the pointer past the offset & block id */
1064 rio_table_hdr = (struct rio_table_hdr *)(ptr+offset+4); 1075 rio_table_hdr = (struct rio_table_hdr *)(ptr + offset + 4);
1065 break; 1076 break;
1066 } 1077 }
1067 /* The next offset is stored in the 1st word. 0 means no more */ 1078 /* The next offset is stored in the 1st word. 0 means no more */
1068 offset = *((unsigned short *)(ptr + offset)); 1079 offset = *((unsigned short *)(ptr + offset));
1069 } 1080 }
1070 if (!rio_table_hdr){ 1081 if (!rio_table_hdr) {
1071 printk(KERN_ERR "Calgary: Unable to locate " 1082 printk(KERN_ERR "Calgary: Unable to locate "
1072 "Rio Grande Table in EBDA - bailing!\n"); 1083 "Rio Grande Table in EBDA - bailing!\n");
1073 return; 1084 return;
1074 } 1085 }
1075 1086
1076 if (build_detail_arrays()) 1087 ret = build_detail_arrays();
1088 if (ret) {
1089 printk(KERN_ERR "Calgary: build_detail_arrays ret %d\n", ret);
1077 return; 1090 return;
1091 }
1078 1092
1079 specified_table_size = determine_tce_table_size(end_pfn * PAGE_SIZE); 1093 specified_table_size = determine_tce_table_size(end_pfn * PAGE_SIZE);
1080 1094
1081 for (bus = 0; bus < MAX_PHB_BUS_NUM; bus++) { 1095 for (bus = 0; bus < MAX_PHB_BUS_NUM; bus++) {
1082 int dev; 1096 int dev;
1083 struct calgary_bus_info *info = &bus_info[bus]; 1097 struct calgary_bus_info *info = &bus_info[bus];
1084 info->phbid = -1;
1085 1098
1086 if (read_pci_config(bus, 0, 0, 0) != PCI_VENDOR_DEVICE_ID_CALGARY) 1099 if (read_pci_config(bus, 0, 0, 0) != PCI_VENDOR_DEVICE_ID_CALGARY)
1087 continue; 1100 continue;