diff options
-rw-r--r-- | arch/powerpc/platforms/powernv/eeh-ioda.c | 234 |
1 files changed, 233 insertions, 1 deletions
diff --git a/arch/powerpc/platforms/powernv/eeh-ioda.c b/arch/powerpc/platforms/powernv/eeh-ioda.c index a76870b6a184..ea5fa05f8bbf 100644 --- a/arch/powerpc/platforms/powernv/eeh-ioda.c +++ b/arch/powerpc/platforms/powernv/eeh-ioda.c | |||
@@ -213,11 +213,243 @@ static int ioda_eeh_get_state(struct eeh_pe *pe) | |||
213 | return result; | 213 | return result; |
214 | } | 214 | } |
215 | 215 | ||
216 | static int ioda_eeh_pe_clear(struct eeh_pe *pe) | ||
217 | { | ||
218 | struct pci_controller *hose; | ||
219 | struct pnv_phb *phb; | ||
220 | u32 pe_no; | ||
221 | u8 fstate; | ||
222 | u16 pcierr; | ||
223 | s64 ret; | ||
224 | |||
225 | pe_no = pe->addr; | ||
226 | hose = pe->phb; | ||
227 | phb = pe->phb->private_data; | ||
228 | |||
229 | /* Clear the EEH error on the PE */ | ||
230 | ret = opal_pci_eeh_freeze_clear(phb->opal_id, | ||
231 | pe_no, OPAL_EEH_ACTION_CLEAR_FREEZE_ALL); | ||
232 | if (ret) { | ||
233 | pr_err("%s: Failed to clear EEH error for " | ||
234 | "PHB#%x-PE#%x, err=%lld\n", | ||
235 | __func__, hose->global_number, pe_no, ret); | ||
236 | return -EIO; | ||
237 | } | ||
238 | |||
239 | /* | ||
240 | * Read the PE state back and verify that the frozen | ||
241 | * state has been removed. | ||
242 | */ | ||
243 | ret = opal_pci_eeh_freeze_status(phb->opal_id, pe_no, | ||
244 | &fstate, &pcierr, NULL); | ||
245 | if (ret) { | ||
246 | pr_err("%s: Failed to get EEH status on " | ||
247 | "PHB#%x-PE#%x\n, err=%lld\n", | ||
248 | __func__, hose->global_number, pe_no, ret); | ||
249 | return -EIO; | ||
250 | } | ||
251 | |||
252 | if (fstate != OPAL_EEH_STOPPED_NOT_FROZEN) { | ||
253 | pr_err("%s: Frozen state not cleared on " | ||
254 | "PHB#%x-PE#%x, sts=%x\n", | ||
255 | __func__, hose->global_number, pe_no, fstate); | ||
256 | return -EIO; | ||
257 | } | ||
258 | |||
259 | return 0; | ||
260 | } | ||
261 | |||
262 | static s64 ioda_eeh_phb_poll(struct pnv_phb *phb) | ||
263 | { | ||
264 | s64 rc = OPAL_HARDWARE; | ||
265 | |||
266 | while (1) { | ||
267 | rc = opal_pci_poll(phb->opal_id); | ||
268 | if (rc <= 0) | ||
269 | break; | ||
270 | |||
271 | msleep(rc); | ||
272 | } | ||
273 | |||
274 | return rc; | ||
275 | } | ||
276 | |||
277 | static int ioda_eeh_phb_reset(struct pci_controller *hose, int option) | ||
278 | { | ||
279 | struct pnv_phb *phb = hose->private_data; | ||
280 | s64 rc = OPAL_HARDWARE; | ||
281 | |||
282 | pr_debug("%s: Reset PHB#%x, option=%d\n", | ||
283 | __func__, hose->global_number, option); | ||
284 | |||
285 | /* Issue PHB complete reset request */ | ||
286 | if (option == EEH_RESET_FUNDAMENTAL || | ||
287 | option == EEH_RESET_HOT) | ||
288 | rc = opal_pci_reset(phb->opal_id, | ||
289 | OPAL_PHB_COMPLETE, | ||
290 | OPAL_ASSERT_RESET); | ||
291 | else if (option == EEH_RESET_DEACTIVATE) | ||
292 | rc = opal_pci_reset(phb->opal_id, | ||
293 | OPAL_PHB_COMPLETE, | ||
294 | OPAL_DEASSERT_RESET); | ||
295 | if (rc < 0) | ||
296 | goto out; | ||
297 | |||
298 | /* | ||
299 | * Poll state of the PHB until the request is done | ||
300 | * successfully. | ||
301 | */ | ||
302 | rc = ioda_eeh_phb_poll(phb); | ||
303 | out: | ||
304 | if (rc != OPAL_SUCCESS) | ||
305 | return -EIO; | ||
306 | |||
307 | return 0; | ||
308 | } | ||
309 | |||
310 | static int ioda_eeh_root_reset(struct pci_controller *hose, int option) | ||
311 | { | ||
312 | struct pnv_phb *phb = hose->private_data; | ||
313 | s64 rc = OPAL_SUCCESS; | ||
314 | |||
315 | pr_debug("%s: Reset PHB#%x, option=%d\n", | ||
316 | __func__, hose->global_number, option); | ||
317 | |||
318 | /* | ||
319 | * During the reset deassert time, we needn't care | ||
320 | * the reset scope because the firmware does nothing | ||
321 | * for fundamental or hot reset during deassert phase. | ||
322 | */ | ||
323 | if (option == EEH_RESET_FUNDAMENTAL) | ||
324 | rc = opal_pci_reset(phb->opal_id, | ||
325 | OPAL_PCI_FUNDAMENTAL_RESET, | ||
326 | OPAL_ASSERT_RESET); | ||
327 | else if (option == EEH_RESET_HOT) | ||
328 | rc = opal_pci_reset(phb->opal_id, | ||
329 | OPAL_PCI_HOT_RESET, | ||
330 | OPAL_ASSERT_RESET); | ||
331 | else if (option == EEH_RESET_DEACTIVATE) | ||
332 | rc = opal_pci_reset(phb->opal_id, | ||
333 | OPAL_PCI_HOT_RESET, | ||
334 | OPAL_DEASSERT_RESET); | ||
335 | if (rc < 0) | ||
336 | goto out; | ||
337 | |||
338 | /* Poll state of the PHB until the request is done */ | ||
339 | rc = ioda_eeh_phb_poll(phb); | ||
340 | out: | ||
341 | if (rc != OPAL_SUCCESS) | ||
342 | return -EIO; | ||
343 | |||
344 | return 0; | ||
345 | } | ||
346 | |||
347 | static int ioda_eeh_bridge_reset(struct pci_controller *hose, | ||
348 | struct pci_dev *dev, int option) | ||
349 | { | ||
350 | u16 ctrl; | ||
351 | |||
352 | pr_debug("%s: Reset device %04x:%02x:%02x.%01x with option %d\n", | ||
353 | __func__, hose->global_number, dev->bus->number, | ||
354 | PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn), option); | ||
355 | |||
356 | switch (option) { | ||
357 | case EEH_RESET_FUNDAMENTAL: | ||
358 | case EEH_RESET_HOT: | ||
359 | pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &ctrl); | ||
360 | ctrl |= PCI_BRIDGE_CTL_BUS_RESET; | ||
361 | pci_write_config_word(dev, PCI_BRIDGE_CONTROL, ctrl); | ||
362 | break; | ||
363 | case EEH_RESET_DEACTIVATE: | ||
364 | pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &ctrl); | ||
365 | ctrl &= ~PCI_BRIDGE_CTL_BUS_RESET; | ||
366 | pci_write_config_word(dev, PCI_BRIDGE_CONTROL, ctrl); | ||
367 | break; | ||
368 | } | ||
369 | |||
370 | return 0; | ||
371 | } | ||
372 | |||
373 | /** | ||
374 | * ioda_eeh_reset - Reset the indicated PE | ||
375 | * @pe: EEH PE | ||
376 | * @option: reset option | ||
377 | * | ||
378 | * Do reset on the indicated PE. For PCI bus sensitive PE, | ||
379 | * we need to reset the parent p2p bridge. The PHB has to | ||
380 | * be reinitialized if the p2p bridge is root bridge. For | ||
381 | * PCI device sensitive PE, we will try to reset the device | ||
382 | * through FLR. For now, we don't have OPAL APIs to do HARD | ||
383 | * reset yet, so all reset would be SOFT (HOT) reset. | ||
384 | */ | ||
385 | static int ioda_eeh_reset(struct eeh_pe *pe, int option) | ||
386 | { | ||
387 | struct pci_controller *hose = pe->phb; | ||
388 | struct eeh_dev *edev; | ||
389 | struct pci_dev *dev; | ||
390 | int ret; | ||
391 | |||
392 | /* | ||
393 | * Anyway, we have to clear the problematic state for the | ||
394 | * corresponding PE. However, we needn't do it if the PE | ||
395 | * is PHB associated. That means the PHB is having fatal | ||
396 | * errors and it needs reset. Further more, the AIB interface | ||
397 | * isn't reliable any more. | ||
398 | */ | ||
399 | if (!(pe->type & EEH_PE_PHB) && | ||
400 | (option == EEH_RESET_HOT || | ||
401 | option == EEH_RESET_FUNDAMENTAL)) { | ||
402 | ret = ioda_eeh_pe_clear(pe); | ||
403 | if (ret) | ||
404 | return -EIO; | ||
405 | } | ||
406 | |||
407 | /* | ||
408 | * The rules applied to reset, either fundamental or hot reset: | ||
409 | * | ||
410 | * We always reset the direct upstream bridge of the PE. If the | ||
411 | * direct upstream bridge isn't root bridge, we always take hot | ||
412 | * reset no matter what option (fundamental or hot) is. Otherwise, | ||
413 | * we should do the reset according to the required option. | ||
414 | */ | ||
415 | if (pe->type & EEH_PE_PHB) { | ||
416 | ret = ioda_eeh_phb_reset(hose, option); | ||
417 | } else { | ||
418 | if (pe->type & EEH_PE_DEVICE) { | ||
419 | /* | ||
420 | * If it's device PE, we didn't refer to the parent | ||
421 | * PCI bus yet. So we have to figure it out indirectly. | ||
422 | */ | ||
423 | edev = list_first_entry(&pe->edevs, | ||
424 | struct eeh_dev, list); | ||
425 | dev = eeh_dev_to_pci_dev(edev); | ||
426 | dev = dev->bus->self; | ||
427 | } else { | ||
428 | /* | ||
429 | * If it's bus PE, the parent PCI bus is already there | ||
430 | * and just pick it up. | ||
431 | */ | ||
432 | dev = pe->bus->self; | ||
433 | } | ||
434 | |||
435 | /* | ||
436 | * Do reset based on the fact that the direct upstream bridge | ||
437 | * is root bridge (port) or not. | ||
438 | */ | ||
439 | if (dev->bus->number == 0) | ||
440 | ret = ioda_eeh_root_reset(hose, option); | ||
441 | else | ||
442 | ret = ioda_eeh_bridge_reset(hose, dev, option); | ||
443 | } | ||
444 | |||
445 | return ret; | ||
446 | } | ||
447 | |||
216 | struct pnv_eeh_ops ioda_eeh_ops = { | 448 | struct pnv_eeh_ops ioda_eeh_ops = { |
217 | .post_init = ioda_eeh_post_init, | 449 | .post_init = ioda_eeh_post_init, |
218 | .set_option = ioda_eeh_set_option, | 450 | .set_option = ioda_eeh_set_option, |
219 | .get_state = ioda_eeh_get_state, | 451 | .get_state = ioda_eeh_get_state, |
220 | .reset = NULL, | 452 | .reset = ioda_eeh_reset, |
221 | .get_log = NULL, | 453 | .get_log = NULL, |
222 | .configure_bridge = NULL, | 454 | .configure_bridge = NULL, |
223 | .next_error = NULL | 455 | .next_error = NULL |