summaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
Diffstat (limited to 'arch')
-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 afc0a53505f..8a1e4f35bc3 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;
static struct rio_table_hdr *rio_table_hdr __initdata;
static struct scal_detail *scal_devs[MAX_NUMNODES] __initdata;
-static struct rio_detail *rio_devs[MAX_NUMNODES*4] __initdata;
+static struct rio_detail *rio_devs[MAX_NUMNODES * 4] __initdata;
struct calgary_bus_info {
void *tce_space;
@@ -855,11 +855,6 @@ static void __init calgary_disable_translation(struct pci_dev *dev)
del_timer_sync(&tbl->watchdog_timer);
}
-static inline void __iomem * __init locate_register_space(struct pci_dev *dev)
-{
- return busno_to_bbar(dev->bus->number);
-}
-
static void __init calgary_init_one_nontraslated(struct pci_dev *dev)
{
pci_dev_get(dev);
@@ -874,15 +869,10 @@ static int __init calgary_init_one(struct pci_dev *dev)
BUG_ON(dev->bus->number >= MAX_PHB_BUS_NUM);
- bbar = locate_register_space(dev);
- if (!bbar) {
- ret = -ENODATA;
- goto done;
- }
-
+ bbar = busno_to_bbar(dev->bus->number);
ret = calgary_setup_tar(dev, bbar);
if (ret)
- goto iounmap;
+ goto done;
pci_dev_get(dev);
dev->bus->self = dev;
@@ -890,38 +880,39 @@ static int __init calgary_init_one(struct pci_dev *dev)
return 0;
-iounmap:
- iounmap(bbar);
done:
return ret;
}
-static int __init calgary_init(void)
+static int __init calgary_locate_bbars(void)
{
- int ret = -ENODEV;
- struct pci_dev *dev = NULL;
- int rio, phb, bus;
+ int ret;
+ int rioidx, phb, bus;
void __iomem *bbar;
void __iomem *target;
+ unsigned long offset;
u8 start_bus, end_bus;
u32 val;
- for (rio = 0; rio < rio_table_hdr->num_rio_dev; rio++) {
+ ret = -ENODATA;
+ for (rioidx = 0; rioidx < rio_table_hdr->num_rio_dev; rioidx++) {
+ struct rio_detail *rio = rio_devs[rioidx];
- if ( (rio_devs[rio]->type != COMPAT_CALGARY) &&
- (rio_devs[rio]->type != ALT_CALGARY) )
+ if ((rio->type != COMPAT_CALGARY) && (rio->type != ALT_CALGARY))
continue;
/* map entire 1MB of Calgary config space */
- bbar = ioremap_nocache(rio_devs[rio]->BBAR, 1024 * 1024);
+ bbar = ioremap_nocache(rio->BBAR, 1024 * 1024);
+ if (!bbar)
+ goto error;
for (phb = 0; phb < PHBS_PER_CALGARY; phb++) {
+ offset = phb_debug_offsets[phb] | PHB_DEBUG_STUFF_OFFSET;
+ target = calgary_reg(bbar, offset);
- target = calgary_reg(bbar, phb_debug_offsets[phb] |
- PHB_DEBUG_STUFF_OFFSET);
val = be32_to_cpu(readl(target));
start_bus = (u8)((val & 0x00FF0000) >> 16);
- end_bus = (u8)((val & 0x0000FF00) >> 8);
+ end_bus = (u8)((val & 0x0000FF00) >> 8);
for (bus = start_bus; bus <= end_bus; bus++) {
bus_info[bus].bbar = bbar;
bus_info[bus].phbid = phb;
@@ -929,6 +920,25 @@ static int __init calgary_init(void)
}
}
+ return 0;
+
+error:
+ /* scan bus_info and iounmap any bbars we previously ioremap'd */
+ for (bus = 0; bus < ARRAY_SIZE(bus_info); bus++)
+ if (bus_info[bus].bbar)
+ iounmap(bus_info[bus].bbar);
+
+ return ret;
+}
+
+static int __init calgary_init(void)
+{
+ int ret;
+ struct pci_dev *dev = NULL;
+
+ ret = calgary_locate_bbars();
+ if (ret)
+ return ret;
do {
dev = pci_get_device(PCI_VENDOR_ID_IBM,
@@ -1000,18 +1010,13 @@ static int __init build_detail_arrays(void)
if (rio_table_hdr->num_scal_dev > MAX_NUMNODES){
printk(KERN_WARNING
- "Calgary: MAX_NUMNODES too low! Defined as %d, "
+ "Calgary: MAX_NUMNODES too low! Defined as %d, "
"but system has %d nodes.\n",
MAX_NUMNODES, rio_table_hdr->num_scal_dev);
return -ENODEV;
}
switch (rio_table_hdr->version){
- default:
- printk(KERN_WARNING
- "Calgary: Invalid Rio Grande Table Version: %d\n",
- rio_table_hdr->version);
- return -ENODEV;
case 2:
scal_detail_size = 11;
rio_detail_size = 13;
@@ -1020,6 +1025,11 @@ static int __init build_detail_arrays(void)
scal_detail_size = 12;
rio_detail_size = 15;
break;
+ default:
+ printk(KERN_WARNING
+ "Calgary: Invalid Rio Grande Table Version: %d\n",
+ rio_table_hdr->version);
+ return -EPROTO;
}
ptr = ((unsigned long)rio_table_hdr) + 3;
@@ -1042,6 +1052,7 @@ void __init detect_calgary(void)
int calgary_found = 0;
unsigned long ptr;
int offset;
+ int ret;
/*
* if the user specified iommu=off or iommu=soft or we found
@@ -1061,27 +1072,29 @@ void __init detect_calgary(void)
/* The block id is stored in the 2nd word */
if (*((unsigned short *)(ptr + offset + 2)) == 0x4752){
/* set the pointer past the offset & block id */
- rio_table_hdr = (struct rio_table_hdr *)(ptr+offset+4);
+ rio_table_hdr = (struct rio_table_hdr *)(ptr + offset + 4);
break;
}
/* The next offset is stored in the 1st word. 0 means no more */
offset = *((unsigned short *)(ptr + offset));
}
- if (!rio_table_hdr){
+ if (!rio_table_hdr) {
printk(KERN_ERR "Calgary: Unable to locate "
"Rio Grande Table in EBDA - bailing!\n");
return;
}
- if (build_detail_arrays())
+ ret = build_detail_arrays();
+ if (ret) {
+ printk(KERN_ERR "Calgary: build_detail_arrays ret %d\n", ret);
return;
+ }
specified_table_size = determine_tce_table_size(end_pfn * PAGE_SIZE);
for (bus = 0; bus < MAX_PHB_BUS_NUM; bus++) {
int dev;
struct calgary_bus_info *info = &bus_info[bus];
- info->phbid = -1;
if (read_pci_config(bus, 0, 0, 0) != PCI_VENDOR_DEVICE_ID_CALGARY)
continue;