diff options
Diffstat (limited to 'arch/ppc64/kernel/rtas_pci.c')
-rw-r--r-- | arch/ppc64/kernel/rtas_pci.c | 54 |
1 files changed, 38 insertions, 16 deletions
diff --git a/arch/ppc64/kernel/rtas_pci.c b/arch/ppc64/kernel/rtas_pci.c index 1048817befb8..4a9719b48abe 100644 --- a/arch/ppc64/kernel/rtas_pci.c +++ b/arch/ppc64/kernel/rtas_pci.c | |||
@@ -48,7 +48,7 @@ static int write_pci_config; | |||
48 | static int ibm_read_pci_config; | 48 | static int ibm_read_pci_config; |
49 | static int ibm_write_pci_config; | 49 | static int ibm_write_pci_config; |
50 | 50 | ||
51 | static int config_access_valid(struct device_node *dn, int where) | 51 | static int config_access_valid(struct pci_dn *dn, int where) |
52 | { | 52 | { |
53 | if (where < 256) | 53 | if (where < 256) |
54 | return 1; | 54 | return 1; |
@@ -58,20 +58,37 @@ static int config_access_valid(struct device_node *dn, int where) | |||
58 | return 0; | 58 | return 0; |
59 | } | 59 | } |
60 | 60 | ||
61 | static int of_device_available(struct device_node * dn) | ||
62 | { | ||
63 | char * status; | ||
64 | |||
65 | status = get_property(dn, "status", NULL); | ||
66 | |||
67 | if (!status) | ||
68 | return 1; | ||
69 | |||
70 | if (!strcmp(status, "okay")) | ||
71 | return 1; | ||
72 | |||
73 | return 0; | ||
74 | } | ||
75 | |||
61 | static int rtas_read_config(struct device_node *dn, int where, int size, u32 *val) | 76 | static int rtas_read_config(struct device_node *dn, int where, int size, u32 *val) |
62 | { | 77 | { |
63 | int returnval = -1; | 78 | int returnval = -1; |
64 | unsigned long buid, addr; | 79 | unsigned long buid, addr; |
65 | int ret; | 80 | int ret; |
81 | struct pci_dn *pdn; | ||
66 | 82 | ||
67 | if (!dn) | 83 | if (!dn || !dn->data) |
68 | return PCIBIOS_DEVICE_NOT_FOUND; | 84 | return PCIBIOS_DEVICE_NOT_FOUND; |
69 | if (!config_access_valid(dn, where)) | 85 | pdn = dn->data; |
86 | if (!config_access_valid(pdn, where)) | ||
70 | return PCIBIOS_BAD_REGISTER_NUMBER; | 87 | return PCIBIOS_BAD_REGISTER_NUMBER; |
71 | 88 | ||
72 | addr = ((where & 0xf00) << 20) | (dn->busno << 16) | | 89 | addr = ((where & 0xf00) << 20) | (pdn->busno << 16) | |
73 | (dn->devfn << 8) | (where & 0xff); | 90 | (pdn->devfn << 8) | (where & 0xff); |
74 | buid = dn->phb->buid; | 91 | buid = pdn->phb->buid; |
75 | if (buid) { | 92 | if (buid) { |
76 | ret = rtas_call(ibm_read_pci_config, 4, 2, &returnval, | 93 | ret = rtas_call(ibm_read_pci_config, 4, 2, &returnval, |
77 | addr, buid >> 32, buid & 0xffffffff, size); | 94 | 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 | |||
83 | if (ret) | 100 | if (ret) |
84 | return PCIBIOS_DEVICE_NOT_FOUND; | 101 | return PCIBIOS_DEVICE_NOT_FOUND; |
85 | 102 | ||
86 | if (returnval == EEH_IO_ERROR_VALUE(size) | 103 | if (returnval == EEH_IO_ERROR_VALUE(size) && |
87 | && eeh_dn_check_failure (dn, NULL)) | 104 | eeh_dn_check_failure (dn, NULL)) |
88 | return PCIBIOS_DEVICE_NOT_FOUND; | 105 | return PCIBIOS_DEVICE_NOT_FOUND; |
89 | 106 | ||
90 | return PCIBIOS_SUCCESSFUL; | 107 | return PCIBIOS_SUCCESSFUL; |
@@ -103,24 +120,28 @@ static int rtas_pci_read_config(struct pci_bus *bus, | |||
103 | 120 | ||
104 | /* Search only direct children of the bus */ | 121 | /* Search only direct children of the bus */ |
105 | for (dn = busdn->child; dn; dn = dn->sibling) | 122 | for (dn = busdn->child; dn; dn = dn->sibling) |
106 | if (dn->devfn == devfn) | 123 | if (dn->data && PCI_DN(dn)->devfn == devfn |
124 | && of_device_available(dn)) | ||
107 | return rtas_read_config(dn, where, size, val); | 125 | return rtas_read_config(dn, where, size, val); |
126 | |||
108 | return PCIBIOS_DEVICE_NOT_FOUND; | 127 | return PCIBIOS_DEVICE_NOT_FOUND; |
109 | } | 128 | } |
110 | 129 | ||
111 | static int rtas_write_config(struct device_node *dn, int where, int size, u32 val) | 130 | int rtas_write_config(struct device_node *dn, int where, int size, u32 val) |
112 | { | 131 | { |
113 | unsigned long buid, addr; | 132 | unsigned long buid, addr; |
114 | int ret; | 133 | int ret; |
134 | struct pci_dn *pdn; | ||
115 | 135 | ||
116 | if (!dn) | 136 | if (!dn || !dn->data) |
117 | return PCIBIOS_DEVICE_NOT_FOUND; | 137 | return PCIBIOS_DEVICE_NOT_FOUND; |
118 | if (!config_access_valid(dn, where)) | 138 | pdn = dn->data; |
139 | if (!config_access_valid(pdn, where)) | ||
119 | return PCIBIOS_BAD_REGISTER_NUMBER; | 140 | return PCIBIOS_BAD_REGISTER_NUMBER; |
120 | 141 | ||
121 | addr = ((where & 0xf00) << 20) | (dn->busno << 16) | | 142 | addr = ((where & 0xf00) << 20) | (pdn->busno << 16) | |
122 | (dn->devfn << 8) | (where & 0xff); | 143 | (pdn->devfn << 8) | (where & 0xff); |
123 | buid = dn->phb->buid; | 144 | buid = pdn->phb->buid; |
124 | if (buid) { | 145 | if (buid) { |
125 | ret = rtas_call(ibm_write_pci_config, 5, 1, NULL, addr, buid >> 32, buid & 0xffffffff, size, (ulong) val); | 146 | ret = rtas_call(ibm_write_pci_config, 5, 1, NULL, addr, buid >> 32, buid & 0xffffffff, size, (ulong) val); |
126 | } else { | 147 | } else { |
@@ -146,7 +167,8 @@ static int rtas_pci_write_config(struct pci_bus *bus, | |||
146 | 167 | ||
147 | /* Search only direct children of the bus */ | 168 | /* Search only direct children of the bus */ |
148 | for (dn = busdn->child; dn; dn = dn->sibling) | 169 | for (dn = busdn->child; dn; dn = dn->sibling) |
149 | if (dn->devfn == devfn) | 170 | if (dn->data && PCI_DN(dn)->devfn == devfn |
171 | && of_device_available(dn)) | ||
150 | return rtas_write_config(dn, where, size, val); | 172 | return rtas_write_config(dn, where, size, val); |
151 | return PCIBIOS_DEVICE_NOT_FOUND; | 173 | return PCIBIOS_DEVICE_NOT_FOUND; |
152 | } | 174 | } |