aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorGavin Shan <shangw@linux.vnet.ibm.com>2014-02-12 02:24:54 -0500
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2014-02-16 19:19:38 -0500
commit5b2e198e50f6ba57081586b853163ea1bb95f1a8 (patch)
tree6c9e5a60e96ac81a9ebe7157609b4c9970d389d6 /arch
parent24b659a13866b935eca72748ce725279bd3c4466 (diff)
powerpc/powernv: Rework EEH reset
When doing reset in order to recover the affected PE, we issue hot reset on PE primary bus if it's not root bus. Otherwise, we issue hot or fundamental reset on root port or PHB accordingly. For the later case, we didn't cover the situation where PE only includes root port and it potentially causes kernel crash upon EEH error to the PE. The patch reworks the logic of EEH reset to improve the code readability and also avoid the kernel crash. Cc: stable@vger.kernel.org Reported-by: Thadeu Lima de Souza Cascardo <cascardo@linux.vnet.ibm.com> Signed-off-by: Gavin Shan <shangw@linux.vnet.ibm.com> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Diffstat (limited to 'arch')
-rw-r--r--arch/powerpc/platforms/powernv/eeh-ioda.c29
1 files changed, 4 insertions, 25 deletions
diff --git a/arch/powerpc/platforms/powernv/eeh-ioda.c b/arch/powerpc/platforms/powernv/eeh-ioda.c
index e1e71618b70c..fcb79cffdb66 100644
--- a/arch/powerpc/platforms/powernv/eeh-ioda.c
+++ b/arch/powerpc/platforms/powernv/eeh-ioda.c
@@ -489,8 +489,7 @@ static int ioda_eeh_bridge_reset(struct pci_controller *hose,
489static int ioda_eeh_reset(struct eeh_pe *pe, int option) 489static int ioda_eeh_reset(struct eeh_pe *pe, int option)
490{ 490{
491 struct pci_controller *hose = pe->phb; 491 struct pci_controller *hose = pe->phb;
492 struct eeh_dev *edev; 492 struct pci_bus *bus;
493 struct pci_dev *dev;
494 int ret; 493 int ret;
495 494
496 /* 495 /*
@@ -519,31 +518,11 @@ static int ioda_eeh_reset(struct eeh_pe *pe, int option)
519 if (pe->type & EEH_PE_PHB) { 518 if (pe->type & EEH_PE_PHB) {
520 ret = ioda_eeh_phb_reset(hose, option); 519 ret = ioda_eeh_phb_reset(hose, option);
521 } else { 520 } else {
522 if (pe->type & EEH_PE_DEVICE) { 521 bus = eeh_pe_bus_get(pe);
523 /* 522 if (pci_is_root_bus(bus))
524 * If it's device PE, we didn't refer to the parent
525 * PCI bus yet. So we have to figure it out indirectly.
526 */
527 edev = list_first_entry(&pe->edevs,
528 struct eeh_dev, list);
529 dev = eeh_dev_to_pci_dev(edev);
530 dev = dev->bus->self;
531 } else {
532 /*
533 * If it's bus PE, the parent PCI bus is already there
534 * and just pick it up.
535 */
536 dev = pe->bus->self;
537 }
538
539 /*
540 * Do reset based on the fact that the direct upstream bridge
541 * is root bridge (port) or not.
542 */
543 if (dev->bus->number == 0)
544 ret = ioda_eeh_root_reset(hose, option); 523 ret = ioda_eeh_root_reset(hose, option);
545 else 524 else
546 ret = ioda_eeh_bridge_reset(hose, dev, option); 525 ret = ioda_eeh_bridge_reset(hose, bus->self, option);
547 } 526 }
548 527
549 return ret; 528 return ret;