aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86_64/kernel/pci-calgary.c
diff options
context:
space:
mode:
authorMuli Ben-Yehuda <muli@il.ibm.com>2006-12-06 20:14:06 -0500
committerAndi Kleen <andi@basil.nowhere.org>2006-12-06 20:14:06 -0500
commiteae93755540bae18aff46b8a0e621b5d65bd5380 (patch)
treee1228183341e2a80200c256ccaac33493444fc5d /arch/x86_64/kernel/pci-calgary.c
parentb34e90b8f0f30151349134f87b5dc6ef75a5218c (diff)
[PATCH] Calgary: check BBAR ioremap success when ioremapping
This patch cleans up the previous "Use BIOS supplied BBAR information" patch. Mostly stylistic clenaups, but also check for ioremap failure when we ioremap the BBAR rather than when trying to use it. Signed-off-by: Muli Ben-Yehuda <muli@il.ibm.com> Signed-off-by: Jon Mason <jdmason@kudzu.us> Signed-off-by: Andi Kleen <ak@suse.de> Acked-by: Laurent Vivier <Laurent.Vivier@bull.net>
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;