aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/platforms
diff options
context:
space:
mode:
authorRichard A Lary <rlary@linux.vnet.ibm.com>2011-04-22 05:59:47 -0400
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2011-05-04 02:02:36 -0400
commit308fc4f8e10b5239cde46104bb9fca79b46230c8 (patch)
tree34b0db6cf863af99453094a922c071c44b46450e /arch/powerpc/platforms
parent9ee820fa005254dfc816330f6654f14dcb2beee1 (diff)
powerpc/pseries/eeh: Propagate needs_freset flag to device at PE
For multifunction adapters with a PCI bridge or switch as the device at the Partitionable Endpoint(PE), if one or more devices below PE sets dev->needs_freset, that value will be set for the PE device. In other words, if any device below PE requires a fundamental reset the PE will request a fundamental reset. Signed-off-by: Richard A Lary <rlary@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/pseries/eeh.c50
1 files changed, 43 insertions, 7 deletions
diff --git a/arch/powerpc/platforms/pseries/eeh.c b/arch/powerpc/platforms/pseries/eeh.c
index 229373053864..6cb3e7bd175d 100644
--- a/arch/powerpc/platforms/pseries/eeh.c
+++ b/arch/powerpc/platforms/pseries/eeh.c
@@ -451,6 +451,39 @@ void eeh_clear_slot (struct device_node *dn, int mode_flag)
451 raw_spin_unlock_irqrestore(&confirm_error_lock, flags); 451 raw_spin_unlock_irqrestore(&confirm_error_lock, flags);
452} 452}
453 453
454void __eeh_set_pe_freset(struct device_node *parent, unsigned int *freset)
455{
456 struct device_node *dn;
457
458 for_each_child_of_node(parent, dn) {
459 if (PCI_DN(dn)) {
460
461 struct pci_dev *dev = PCI_DN(dn)->pcidev;
462
463 if (dev && dev->driver)
464 *freset |= dev->needs_freset;
465
466 __eeh_set_pe_freset(dn, freset);
467 }
468 }
469}
470
471void eeh_set_pe_freset(struct device_node *dn, unsigned int *freset)
472{
473 struct pci_dev *dev;
474 dn = find_device_pe(dn);
475
476 /* Back up one, since config addrs might be shared */
477 if (!pcibios_find_pci_bus(dn) && PCI_DN(dn->parent))
478 dn = dn->parent;
479
480 dev = PCI_DN(dn)->pcidev;
481 if (dev)
482 *freset |= dev->needs_freset;
483
484 __eeh_set_pe_freset(dn, freset);
485}
486
454/** 487/**
455 * eeh_dn_check_failure - check if all 1's data is due to EEH slot freeze 488 * eeh_dn_check_failure - check if all 1's data is due to EEH slot freeze
456 * @dn device node 489 * @dn device node
@@ -739,18 +772,21 @@ int pcibios_set_pcie_reset_state(struct pci_dev *dev, enum pcie_reset_state stat
739/** 772/**
740 * rtas_set_slot_reset -- assert the pci #RST line for 1/4 second 773 * rtas_set_slot_reset -- assert the pci #RST line for 1/4 second
741 * @pdn: pci device node to be reset. 774 * @pdn: pci device node to be reset.
742 *
743 * Return 0 if success, else a non-zero value.
744 */ 775 */
745 776
746static void __rtas_set_slot_reset(struct pci_dn *pdn) 777static void __rtas_set_slot_reset(struct pci_dn *pdn)
747{ 778{
748 struct pci_dev *dev = pdn->pcidev; 779 unsigned int freset = 0;
749 780
750 /* Determine type of EEH reset required by device, 781 /* Determine type of EEH reset required for
751 * default hot reset or fundamental reset 782 * Partitionable Endpoint, a hot-reset (1)
752 */ 783 * or a fundamental reset (3).
753 if (dev && dev->needs_freset) 784 * A fundamental reset required by any device under
785 * Partitionable Endpoint trumps hot-reset.
786 */
787 eeh_set_pe_freset(pdn->node, &freset);
788
789 if (freset)
754 rtas_pci_slot_reset(pdn, 3); 790 rtas_pci_slot_reset(pdn, 3);
755 else 791 else
756 rtas_pci_slot_reset(pdn, 1); 792 rtas_pci_slot_reset(pdn, 1);