diff options
author | Gavin Shan <shangw@linux.vnet.ibm.com> | 2013-06-20 01:21:09 -0400 |
---|---|---|
committer | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2013-06-20 03:06:30 -0400 |
commit | 8c41a7f3f7593fe57578f3f649232a5842d4c65d (patch) | |
tree | cc48fa00696bc9f0d3bf3cfce842f075bbe260bd /arch/powerpc/platforms | |
parent | eb0059836baa14c58ebad030684846213aaece89 (diff) |
powerpc/eeh: I/O chip EEH state retrieval
The patch adds I/O chip backend to retrieve the state for the
indicated PE. While the PE state is temperarily unavailable,
the upper layer (powernv platform) should return default delay
(1 second).
Signed-off-by: Gavin Shan <shangw@linux.vnet.ibm.com>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Diffstat (limited to 'arch/powerpc/platforms')
-rw-r--r-- | arch/powerpc/platforms/powernv/eeh-ioda.c | 99 |
1 files changed, 98 insertions, 1 deletions
diff --git a/arch/powerpc/platforms/powernv/eeh-ioda.c b/arch/powerpc/platforms/powernv/eeh-ioda.c index 744eb9e39be2..a76870b6a184 100644 --- a/arch/powerpc/platforms/powernv/eeh-ioda.c +++ b/arch/powerpc/platforms/powernv/eeh-ioda.c | |||
@@ -116,10 +116,107 @@ static int ioda_eeh_set_option(struct eeh_pe *pe, int option) | |||
116 | return ret; | 116 | return ret; |
117 | } | 117 | } |
118 | 118 | ||
119 | /** | ||
120 | * ioda_eeh_get_state - Retrieve the state of PE | ||
121 | * @pe: EEH PE | ||
122 | * | ||
123 | * The PE's state should be retrieved from the PEEV, PEST | ||
124 | * IODA tables. Since the OPAL has exported the function | ||
125 | * to do it, it'd better to use that. | ||
126 | */ | ||
127 | static int ioda_eeh_get_state(struct eeh_pe *pe) | ||
128 | { | ||
129 | s64 ret = 0; | ||
130 | u8 fstate; | ||
131 | u16 pcierr; | ||
132 | u32 pe_no; | ||
133 | int result; | ||
134 | struct pci_controller *hose = pe->phb; | ||
135 | struct pnv_phb *phb = hose->private_data; | ||
136 | |||
137 | /* | ||
138 | * Sanity check on PE address. The PHB PE address should | ||
139 | * be zero. | ||
140 | */ | ||
141 | if (pe->addr < 0 || pe->addr >= phb->ioda.total_pe) { | ||
142 | pr_err("%s: PE address %x out of range [0, %x] " | ||
143 | "on PHB#%x\n", | ||
144 | __func__, pe->addr, phb->ioda.total_pe, | ||
145 | hose->global_number); | ||
146 | return EEH_STATE_NOT_SUPPORT; | ||
147 | } | ||
148 | |||
149 | /* Retrieve PE status through OPAL */ | ||
150 | pe_no = pe->addr; | ||
151 | ret = opal_pci_eeh_freeze_status(phb->opal_id, pe_no, | ||
152 | &fstate, &pcierr, NULL); | ||
153 | if (ret) { | ||
154 | pr_err("%s: Failed to get EEH status on " | ||
155 | "PHB#%x-PE#%x\n, err=%lld\n", | ||
156 | __func__, hose->global_number, pe_no, ret); | ||
157 | return EEH_STATE_NOT_SUPPORT; | ||
158 | } | ||
159 | |||
160 | /* Check PHB status */ | ||
161 | if (pe->type & EEH_PE_PHB) { | ||
162 | result = 0; | ||
163 | result &= ~EEH_STATE_RESET_ACTIVE; | ||
164 | |||
165 | if (pcierr != OPAL_EEH_PHB_ERROR) { | ||
166 | result |= EEH_STATE_MMIO_ACTIVE; | ||
167 | result |= EEH_STATE_DMA_ACTIVE; | ||
168 | result |= EEH_STATE_MMIO_ENABLED; | ||
169 | result |= EEH_STATE_DMA_ENABLED; | ||
170 | } | ||
171 | |||
172 | return result; | ||
173 | } | ||
174 | |||
175 | /* Parse result out */ | ||
176 | result = 0; | ||
177 | switch (fstate) { | ||
178 | case OPAL_EEH_STOPPED_NOT_FROZEN: | ||
179 | result &= ~EEH_STATE_RESET_ACTIVE; | ||
180 | result |= EEH_STATE_MMIO_ACTIVE; | ||
181 | result |= EEH_STATE_DMA_ACTIVE; | ||
182 | result |= EEH_STATE_MMIO_ENABLED; | ||
183 | result |= EEH_STATE_DMA_ENABLED; | ||
184 | break; | ||
185 | case OPAL_EEH_STOPPED_MMIO_FREEZE: | ||
186 | result &= ~EEH_STATE_RESET_ACTIVE; | ||
187 | result |= EEH_STATE_DMA_ACTIVE; | ||
188 | result |= EEH_STATE_DMA_ENABLED; | ||
189 | break; | ||
190 | case OPAL_EEH_STOPPED_DMA_FREEZE: | ||
191 | result &= ~EEH_STATE_RESET_ACTIVE; | ||
192 | result |= EEH_STATE_MMIO_ACTIVE; | ||
193 | result |= EEH_STATE_MMIO_ENABLED; | ||
194 | break; | ||
195 | case OPAL_EEH_STOPPED_MMIO_DMA_FREEZE: | ||
196 | result &= ~EEH_STATE_RESET_ACTIVE; | ||
197 | break; | ||
198 | case OPAL_EEH_STOPPED_RESET: | ||
199 | result |= EEH_STATE_RESET_ACTIVE; | ||
200 | break; | ||
201 | case OPAL_EEH_STOPPED_TEMP_UNAVAIL: | ||
202 | result |= EEH_STATE_UNAVAILABLE; | ||
203 | break; | ||
204 | case OPAL_EEH_STOPPED_PERM_UNAVAIL: | ||
205 | result |= EEH_STATE_NOT_SUPPORT; | ||
206 | break; | ||
207 | default: | ||
208 | pr_warning("%s: Unexpected EEH status 0x%x " | ||
209 | "on PHB#%x-PE#%x\n", | ||
210 | __func__, fstate, hose->global_number, pe_no); | ||
211 | } | ||
212 | |||
213 | return result; | ||
214 | } | ||
215 | |||
119 | struct pnv_eeh_ops ioda_eeh_ops = { | 216 | struct pnv_eeh_ops ioda_eeh_ops = { |
120 | .post_init = ioda_eeh_post_init, | 217 | .post_init = ioda_eeh_post_init, |
121 | .set_option = ioda_eeh_set_option, | 218 | .set_option = ioda_eeh_set_option, |
122 | .get_state = NULL, | 219 | .get_state = ioda_eeh_get_state, |
123 | .reset = NULL, | 220 | .reset = NULL, |
124 | .get_log = NULL, | 221 | .get_log = NULL, |
125 | .configure_bridge = NULL, | 222 | .configure_bridge = NULL, |