aboutsummaryrefslogtreecommitdiff
path: root/arch/ppc64/kernel
diff options
context:
space:
mode:
authorJake Moilanen <moilanen@austin.ibm.com>2005-06-09 09:31:12 -0500
committerPaul Mackerras <paulus@samba.org>2005-08-29 10:53:31 +1000
commit293da76b3d4c2f362f906bce8c5d2e053bdf8d44 (patch)
tree8df51f65e8fafd152ce0fa57fd0fe9ef56659ef1 /arch/ppc64/kernel
parent34153fa3af45d84f3221d9b67ba2ab7e8a220d28 (diff)
[PATCH] ppc64: PCI device-node failure detection
OpenFirmware marks devices as failed in the device-tree when a hardware problem is detected. The kernel needs to fail config reads/writes to prevent a kernel crash when incorrect data is read. This patch validates that the device-node is not marked "fail" when config space reads/writes are attempted. Signed-off-by: Jake Moilanen <moilanen@austin.ibm.com> Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch/ppc64/kernel')
-rw-r--r--arch/ppc64/kernel/rtas_pci.c19
1 files changed, 17 insertions, 2 deletions
diff --git a/arch/ppc64/kernel/rtas_pci.c b/arch/ppc64/kernel/rtas_pci.c
index 1048817befb..1dccadaddd1 100644
--- a/arch/ppc64/kernel/rtas_pci.c
+++ b/arch/ppc64/kernel/rtas_pci.c
@@ -58,6 +58,21 @@ 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;
@@ -103,7 +118,7 @@ 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->devfn == devfn && of_device_available(dn))
return rtas_read_config(dn, where, size, val);
return PCIBIOS_DEVICE_NOT_FOUND;
}
@@ -146,7 +161,7 @@ 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->devfn == devfn && of_device_available(dn))
return rtas_write_config(dn, where, size, val);
return PCIBIOS_DEVICE_NOT_FOUND;
}