Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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>

authored by

Gavin Shan and committed by
Benjamin Herrenschmidt
5b2e198e 24b659a1

+4 -25
+4 -25
arch/powerpc/platforms/powernv/eeh-ioda.c
··· 489 489 static int ioda_eeh_reset(struct eeh_pe *pe, int option) 490 490 { 491 491 struct pci_controller *hose = pe->phb; 492 - struct eeh_dev *edev; 493 - struct pci_dev *dev; 492 + struct pci_bus *bus; 494 493 int ret; 495 494 496 495 /* ··· 518 519 if (pe->type & EEH_PE_PHB) { 519 520 ret = ioda_eeh_phb_reset(hose, option); 520 521 } else { 521 - if (pe->type & EEH_PE_DEVICE) { 522 - /* 523 - * If it's device PE, we didn't refer to the parent 524 - * PCI bus yet. So we have to figure it out indirectly. 525 - */ 526 - edev = list_first_entry(&pe->edevs, 527 - struct eeh_dev, list); 528 - dev = eeh_dev_to_pci_dev(edev); 529 - dev = dev->bus->self; 530 - } else { 531 - /* 532 - * If it's bus PE, the parent PCI bus is already there 533 - * and just pick it up. 534 - */ 535 - dev = pe->bus->self; 536 - } 537 - 538 - /* 539 - * Do reset based on the fact that the direct upstream bridge 540 - * is root bridge (port) or not. 541 - */ 542 - if (dev->bus->number == 0) 522 + bus = eeh_pe_bus_get(pe); 523 + if (pci_is_root_bus(bus)) 543 524 ret = ioda_eeh_root_reset(hose, option); 544 525 else 545 - ret = ioda_eeh_bridge_reset(hose, dev, option); 526 + ret = ioda_eeh_bridge_reset(hose, bus->self, option); 546 527 } 547 528 548 529 return ret;