Merge master.kernel.org:/home/rmk/linux-2.6-arm
[pandora-kernel.git] / arch / ppc64 / kernel / rtas_pci.c
index 1048817..4a9719b 100644 (file)
@@ -48,7 +48,7 @@ static int write_pci_config;
 static int ibm_read_pci_config;
 static int ibm_write_pci_config;
 
-static int config_access_valid(struct device_node *dn, int where)
+static int config_access_valid(struct pci_dn *dn, int where)
 {
        if (where < 256)
                return 1;
@@ -58,20 +58,37 @@ static int config_access_valid(struct device_node *dn, int where)
        return 0;
 }
 
+static int of_device_available(struct device_node * dn)
+{
+        char * status;
+
+        status = get_property(dn, "status", NULL);
+
+        if (!status)
+                return 1;
+
+        if (!strcmp(status, "okay"))
+                return 1;
+
+        return 0;
+}
+
 static int rtas_read_config(struct device_node *dn, int where, int size, u32 *val)
 {
        int returnval = -1;
        unsigned long buid, addr;
        int ret;
+       struct pci_dn *pdn;
 
-       if (!dn)
+       if (!dn || !dn->data)
                return PCIBIOS_DEVICE_NOT_FOUND;
-       if (!config_access_valid(dn, where))
+       pdn = dn->data;
+       if (!config_access_valid(pdn, where))
                return PCIBIOS_BAD_REGISTER_NUMBER;
 
-       addr = ((where & 0xf00) << 20) | (dn->busno << 16) |
-               (dn->devfn << 8) | (where & 0xff);
-       buid = dn->phb->buid;
+       addr = ((where & 0xf00) << 20) | (pdn->busno << 16) |
+               (pdn->devfn << 8) | (where & 0xff);
+       buid = pdn->phb->buid;
        if (buid) {
                ret = rtas_call(ibm_read_pci_config, 4, 2, &returnval,
                                addr, buid >> 32, buid & 0xffffffff, size);
@@ -83,8 +100,8 @@ static int rtas_read_config(struct device_node *dn, int where, int size, u32 *va
        if (ret)
                return PCIBIOS_DEVICE_NOT_FOUND;
 
-       if (returnval == EEH_IO_ERROR_VALUE(size)
-           && eeh_dn_check_failure (dn, NULL))
+       if (returnval == EEH_IO_ERROR_VALUE(size) &&
+           eeh_dn_check_failure (dn, NULL))
                return PCIBIOS_DEVICE_NOT_FOUND;
 
        return PCIBIOS_SUCCESSFUL;
@@ -103,24 +120,28 @@ static int rtas_pci_read_config(struct pci_bus *bus,
 
        /* Search only direct children of the bus */
        for (dn = busdn->child; dn; dn = dn->sibling)
-               if (dn->devfn == devfn)
+               if (dn->data && PCI_DN(dn)->devfn == devfn
+                   && of_device_available(dn))
                        return rtas_read_config(dn, where, size, val);
+
        return PCIBIOS_DEVICE_NOT_FOUND;
 }
 
-static int rtas_write_config(struct device_node *dn, int where, int size, u32 val)
+int rtas_write_config(struct device_node *dn, int where, int size, u32 val)
 {
        unsigned long buid, addr;
        int ret;
+       struct pci_dn *pdn;
 
-       if (!dn)
+       if (!dn || !dn->data)
                return PCIBIOS_DEVICE_NOT_FOUND;
-       if (!config_access_valid(dn, where))
+       pdn = dn->data;
+       if (!config_access_valid(pdn, where))
                return PCIBIOS_BAD_REGISTER_NUMBER;
 
-       addr = ((where & 0xf00) << 20) | (dn->busno << 16) |
-               (dn->devfn << 8) | (where & 0xff);
-       buid = dn->phb->buid;
+       addr = ((where & 0xf00) << 20) | (pdn->busno << 16) |
+               (pdn->devfn << 8) | (where & 0xff);
+       buid = pdn->phb->buid;
        if (buid) {
                ret = rtas_call(ibm_write_pci_config, 5, 1, NULL, addr, buid >> 32, buid & 0xffffffff, size, (ulong) val);
        } else {
@@ -146,7 +167,8 @@ static int rtas_pci_write_config(struct pci_bus *bus,
 
        /* Search only direct children of the bus */
        for (dn = busdn->child; dn; dn = dn->sibling)
-               if (dn->devfn == devfn)
+               if (dn->data && PCI_DN(dn)->devfn == devfn
+                   && of_device_available(dn))
                        return rtas_write_config(dn, where, size, val);
        return PCIBIOS_DEVICE_NOT_FOUND;
 }