aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/platforms
diff options
context:
space:
mode:
authorGavin Shan <gwshan@linux.vnet.ibm.com>2014-07-21 00:42:32 -0400
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2014-08-05 02:33:21 -0400
commitc979c70ed176518dfb32eaf8a7ac58f41ae21de1 (patch)
tree938ae6764ab951385dfa1ba814e4c24611de409a /arch/powerpc/platforms
parent5ca27efbd8b4579ef1e54e6c0a4a73dbf7f56a4a (diff)
powerpc/powernv: Split ioda_eeh_get_state()
Function ioda_eeh_get_state() is used to fetch EEH state for PHB or PE. We're going to support compound PE and the function becomes more complicated with that. The patch splits the function into two functions for PHB and PE cases separately to improve readability. Signed-off-by: Gavin Shan <gwshan@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.c184
1 files changed, 104 insertions, 80 deletions
diff --git a/arch/powerpc/platforms/powernv/eeh-ioda.c b/arch/powerpc/platforms/powernv/eeh-ioda.c
index f4d0259a63c3..09cf80be462c 100644
--- a/arch/powerpc/platforms/powernv/eeh-ioda.c
+++ b/arch/powerpc/platforms/powernv/eeh-ioda.c
@@ -251,122 +251,119 @@ static void ioda_eeh_phb_diag(struct eeh_pe *pe)
251 __func__, pe->phb->global_number, rc); 251 __func__, pe->phb->global_number, rc);
252} 252}
253 253
254/** 254static int ioda_eeh_get_phb_state(struct eeh_pe *pe)
255 * ioda_eeh_get_state - Retrieve the state of PE
256 * @pe: EEH PE
257 *
258 * The PE's state should be retrieved from the PEEV, PEST
259 * IODA tables. Since the OPAL has exported the function
260 * to do it, it'd better to use that.
261 */
262static int ioda_eeh_get_state(struct eeh_pe *pe)
263{ 255{
264 s64 ret = 0; 256 struct pnv_phb *phb = pe->phb->private_data;
265 u8 fstate; 257 u8 fstate;
266 __be16 pcierr; 258 __be16 pcierr;
267 u32 pe_no; 259 s64 rc;
268 int result; 260 int result = 0;
269 struct pci_controller *hose = pe->phb; 261
270 struct pnv_phb *phb = hose->private_data; 262 rc = opal_pci_eeh_freeze_status(phb->opal_id,
263 pe->addr,
264 &fstate,
265 &pcierr,
266 NULL);
267 if (rc != OPAL_SUCCESS) {
268 pr_warn("%s: Failure %lld getting PHB#%x state\n",
269 __func__, rc, phb->hose->global_number);
270 return EEH_STATE_NOT_SUPPORT;
271 }
271 272
272 /* 273 /*
273 * Sanity check on PE address. The PHB PE address should 274 * Check PHB state. If the PHB is frozen for the
274 * be zero. 275 * first time, to dump the PHB diag-data.
275 */ 276 */
276 if (pe->addr < 0 || pe->addr >= phb->ioda.total_pe) { 277 if (be16_to_cpu(pcierr) != OPAL_EEH_PHB_ERROR) {
277 pr_err("%s: PE address %x out of range [0, %x] " 278 result = (EEH_STATE_MMIO_ACTIVE |
278 "on PHB#%x\n", 279 EEH_STATE_DMA_ACTIVE |
279 __func__, pe->addr, phb->ioda.total_pe, 280 EEH_STATE_MMIO_ENABLED |
280 hose->global_number); 281 EEH_STATE_DMA_ENABLED);
281 return EEH_STATE_NOT_SUPPORT; 282 } else if (!(pe->state & EEH_PE_ISOLATED)) {
283 eeh_pe_state_mark(pe, EEH_PE_ISOLATED);
284 ioda_eeh_phb_diag(pe);
282 } 285 }
283 286
287 return result;
288}
289
290static int ioda_eeh_get_pe_state(struct eeh_pe *pe)
291{
292 struct pnv_phb *phb = pe->phb->private_data;
293 u8 fstate;
294 __be16 pcierr;
295 s64 rc;
296 int result;
297
284 /* 298 /*
285 * If we're in middle of PE reset, return normal 299 * We don't clobber hardware frozen state until PE
286 * state to keep EEH core going. For PHB reset, we 300 * reset is completed. In order to keep EEH core
287 * still expect to have fenced PHB cleared with 301 * moving forward, we have to return operational
288 * PHB reset. 302 * state during PE reset.
289 */ 303 */
290 if (!(pe->type & EEH_PE_PHB) && 304 if (pe->state & EEH_PE_RESET) {
291 (pe->state & EEH_PE_RESET)) { 305 result = (EEH_STATE_MMIO_ACTIVE |
292 result = (EEH_STATE_MMIO_ACTIVE | 306 EEH_STATE_DMA_ACTIVE |
293 EEH_STATE_DMA_ACTIVE |
294 EEH_STATE_MMIO_ENABLED | 307 EEH_STATE_MMIO_ENABLED |
295 EEH_STATE_DMA_ENABLED); 308 EEH_STATE_DMA_ENABLED);
296 return result; 309 return result;
297 } 310 }
298 311
299 /* Retrieve PE status through OPAL */ 312 /* Fetch state from hardware */
300 pe_no = pe->addr; 313 rc = opal_pci_eeh_freeze_status(phb->opal_id,
301 ret = opal_pci_eeh_freeze_status(phb->opal_id, pe_no, 314 pe->addr,
302 &fstate, &pcierr, NULL); 315 &fstate,
303 if (ret) { 316 &pcierr,
304 pr_err("%s: Failed to get EEH status on " 317 NULL);
305 "PHB#%x-PE#%x\n, err=%lld\n", 318 if (rc != OPAL_SUCCESS) {
306 __func__, hose->global_number, pe_no, ret); 319 pr_warn("%s: Failure %lld getting PHB#%x-PE%x state\n",
320 __func__, rc, phb->hose->global_number, pe->addr);
307 return EEH_STATE_NOT_SUPPORT; 321 return EEH_STATE_NOT_SUPPORT;
308 } 322 }
309 323
310 /* Check PHB status */ 324 /* Figure out state */
311 if (pe->type & EEH_PE_PHB) {
312 result = 0;
313 result &= ~EEH_STATE_RESET_ACTIVE;
314
315 if (be16_to_cpu(pcierr) != OPAL_EEH_PHB_ERROR) {
316 result |= EEH_STATE_MMIO_ACTIVE;
317 result |= EEH_STATE_DMA_ACTIVE;
318 result |= EEH_STATE_MMIO_ENABLED;
319 result |= EEH_STATE_DMA_ENABLED;
320 } else if (!(pe->state & EEH_PE_ISOLATED)) {
321 eeh_pe_state_mark(pe, EEH_PE_ISOLATED);
322 ioda_eeh_phb_diag(pe);
323 }
324
325 return result;
326 }
327
328 /* Parse result out */
329 result = 0;
330 switch (fstate) { 325 switch (fstate) {
331 case OPAL_EEH_STOPPED_NOT_FROZEN: 326 case OPAL_EEH_STOPPED_NOT_FROZEN:
332 result &= ~EEH_STATE_RESET_ACTIVE; 327 result = (EEH_STATE_MMIO_ACTIVE |
333 result |= EEH_STATE_MMIO_ACTIVE; 328 EEH_STATE_DMA_ACTIVE |
334 result |= EEH_STATE_DMA_ACTIVE; 329 EEH_STATE_MMIO_ENABLED |
335 result |= EEH_STATE_MMIO_ENABLED; 330 EEH_STATE_DMA_ENABLED);
336 result |= EEH_STATE_DMA_ENABLED;
337 break; 331 break;
338 case OPAL_EEH_STOPPED_MMIO_FREEZE: 332 case OPAL_EEH_STOPPED_MMIO_FREEZE:
339 result &= ~EEH_STATE_RESET_ACTIVE; 333 result = (EEH_STATE_DMA_ACTIVE |
340 result |= EEH_STATE_DMA_ACTIVE; 334 EEH_STATE_DMA_ENABLED);
341 result |= EEH_STATE_DMA_ENABLED;
342 break; 335 break;
343 case OPAL_EEH_STOPPED_DMA_FREEZE: 336 case OPAL_EEH_STOPPED_DMA_FREEZE:
344 result &= ~EEH_STATE_RESET_ACTIVE; 337 result = (EEH_STATE_MMIO_ACTIVE |
345 result |= EEH_STATE_MMIO_ACTIVE; 338 EEH_STATE_MMIO_ENABLED);
346 result |= EEH_STATE_MMIO_ENABLED;
347 break; 339 break;
348 case OPAL_EEH_STOPPED_MMIO_DMA_FREEZE: 340 case OPAL_EEH_STOPPED_MMIO_DMA_FREEZE:
349 result &= ~EEH_STATE_RESET_ACTIVE; 341 result = 0;
350 break; 342 break;
351 case OPAL_EEH_STOPPED_RESET: 343 case OPAL_EEH_STOPPED_RESET:
352 result |= EEH_STATE_RESET_ACTIVE; 344 result = EEH_STATE_RESET_ACTIVE;
353 break; 345 break;
354 case OPAL_EEH_STOPPED_TEMP_UNAVAIL: 346 case OPAL_EEH_STOPPED_TEMP_UNAVAIL:
355 result |= EEH_STATE_UNAVAILABLE; 347 result = EEH_STATE_UNAVAILABLE;
356 break; 348 break;
357 case OPAL_EEH_STOPPED_PERM_UNAVAIL: 349 case OPAL_EEH_STOPPED_PERM_UNAVAIL:
358 result |= EEH_STATE_NOT_SUPPORT; 350 result = EEH_STATE_NOT_SUPPORT;
359 break; 351 break;
360 default: 352 default:
361 pr_warning("%s: Unexpected EEH status 0x%x " 353 result = EEH_STATE_NOT_SUPPORT;
362 "on PHB#%x-PE#%x\n", 354 pr_warn("%s: Invalid PHB#%x-PE#%x state %x\n",
363 __func__, fstate, hose->global_number, pe_no); 355 __func__, phb->hose->global_number,
356 pe->addr, fstate);
364 } 357 }
365 358
366 /* Dump PHB diag-data for frozen PE */ 359 /*
367 if (result != EEH_STATE_NOT_SUPPORT && 360 * If the PE is switching to frozen state for the
368 (result & (EEH_STATE_MMIO_ACTIVE | EEH_STATE_DMA_ACTIVE)) != 361 * first time, to dump the PHB diag-data.
369 (EEH_STATE_MMIO_ACTIVE | EEH_STATE_DMA_ACTIVE) && 362 */
363 if (!(result & EEH_STATE_NOT_SUPPORT) &&
364 !(result & EEH_STATE_UNAVAILABLE) &&
365 !(result & EEH_STATE_MMIO_ACTIVE) &&
366 !(result & EEH_STATE_DMA_ACTIVE) &&
370 !(pe->state & EEH_PE_ISOLATED)) { 367 !(pe->state & EEH_PE_ISOLATED)) {
371 eeh_pe_state_mark(pe, EEH_PE_ISOLATED); 368 eeh_pe_state_mark(pe, EEH_PE_ISOLATED);
372 ioda_eeh_phb_diag(pe); 369 ioda_eeh_phb_diag(pe);
@@ -375,6 +372,33 @@ static int ioda_eeh_get_state(struct eeh_pe *pe)
375 return result; 372 return result;
376} 373}
377 374
375/**
376 * ioda_eeh_get_state - Retrieve the state of PE
377 * @pe: EEH PE
378 *
379 * The PE's state should be retrieved from the PEEV, PEST
380 * IODA tables. Since the OPAL has exported the function
381 * to do it, it'd better to use that.
382 */
383static int ioda_eeh_get_state(struct eeh_pe *pe)
384{
385 struct pnv_phb *phb = pe->phb->private_data;
386
387 /* Sanity check on PE number. PHB PE should have 0 */
388 if (pe->addr < 0 ||
389 pe->addr >= phb->ioda.total_pe) {
390 pr_warn("%s: PHB#%x-PE#%x out of range [0, %x]\n",
391 __func__, phb->hose->global_number,
392 pe->addr, phb->ioda.total_pe);
393 return EEH_STATE_NOT_SUPPORT;
394 }
395
396 if (pe->type & EEH_PE_PHB)
397 return ioda_eeh_get_phb_state(pe);
398
399 return ioda_eeh_get_pe_state(pe);
400}
401
378static s64 ioda_eeh_phb_poll(struct pnv_phb *phb) 402static s64 ioda_eeh_phb_poll(struct pnv_phb *phb)
379{ 403{
380 s64 rc = OPAL_HARDWARE; 404 s64 rc = OPAL_HARDWARE;