Skip to content

Commit

Permalink
powrpc/powernv: Reset PHB in kdump kernel
Browse files Browse the repository at this point in the history
In the kdump scenario, the first kerenl doesn't shutdown PCI devices
and the kdump kerenl clean PHB IODA table at the early probe time.
That means the kdump kerenl can't support PCI transactions piled
by the first kerenl. Otherwise, lots of EEH errors and frozen PEs
will be detected.

In order to avoid the EEH errors, the PHB is resetted to drop all
PCI transaction from the first kerenl.

Signed-off-by: Gavin Shan <gwshan@linux.vnet.ibm.com>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
  • Loading branch information
Gavin Shan authored and Benjamin Herrenschmidt committed Apr 28, 2014
1 parent d92a208 commit 361f2a2
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 4 deletions.
15 changes: 11 additions & 4 deletions arch/powerpc/platforms/powernv/eeh-ioda.c
Original file line number Diff line number Diff line change
Expand Up @@ -388,13 +388,16 @@ static s64 ioda_eeh_phb_poll(struct pnv_phb *phb)
if (rc <= 0)
break;

msleep(rc);
if (system_state < SYSTEM_RUNNING)
udelay(1000 * rc);
else
msleep(rc);
}

return rc;
}

static int ioda_eeh_phb_reset(struct pci_controller *hose, int option)
int ioda_eeh_phb_reset(struct pci_controller *hose, int option)
{
struct pnv_phb *phb = hose->private_data;
s64 rc = OPAL_HARDWARE;
Expand Down Expand Up @@ -422,8 +425,12 @@ static int ioda_eeh_phb_reset(struct pci_controller *hose, int option)
* need the PCI bus settlement delay.
*/
rc = ioda_eeh_phb_poll(phb);
if (option == EEH_RESET_DEACTIVATE)
msleep(EEH_PE_RST_SETTLE_TIME);
if (option == EEH_RESET_DEACTIVATE) {
if (system_state < SYSTEM_RUNNING)
udelay(1000 * EEH_PE_RST_SETTLE_TIME);
else
msleep(EEH_PE_RST_SETTLE_TIME);
}
out:
if (rc != OPAL_SUCCESS)
return -EIO;
Expand Down
12 changes: 12 additions & 0 deletions arch/powerpc/platforms/powernv/pci-ioda.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

#include <linux/kernel.h>
#include <linux/pci.h>
#include <linux/crash_dump.h>
#include <linux/debugfs.h>
#include <linux/delay.h>
#include <linux/string.h>
Expand Down Expand Up @@ -1393,6 +1394,17 @@ void __init pnv_pci_init_ioda_phb(struct device_node *np,
rc = opal_pci_reset(phb_id, OPAL_PCI_IODA_TABLE_RESET, OPAL_ASSERT_RESET);
if (rc)
pr_warning(" OPAL Error %ld performing IODA table reset !\n", rc);

/* If we're running in kdump kerenl, the previous kerenl never
* shutdown PCI devices correctly. We already got IODA table
* cleaned out. So we have to issue PHB reset to stop all PCI
* transactions from previous kerenl.
*/
if (is_kdump_kernel()) {
pr_info(" Issue PHB reset ...\n");
ioda_eeh_phb_reset(hose, EEH_RESET_FUNDAMENTAL);
ioda_eeh_phb_reset(hose, OPAL_DEASSERT_RESET);
}
}

void __init pnv_pci_init_ioda2_phb(struct device_node *np)
Expand Down
1 change: 1 addition & 0 deletions arch/powerpc/platforms/powernv/pci.h
Original file line number Diff line number Diff line change
Expand Up @@ -205,5 +205,6 @@ extern void pnv_pci_init_ioda2_phb(struct device_node *np);
extern void pnv_pci_ioda_tce_invalidate(struct iommu_table *tbl,
__be64 *startp, __be64 *endp, bool rm);
extern void pnv_pci_reset_secondary_bus(struct pci_dev *dev);
extern int ioda_eeh_phb_reset(struct pci_controller *hose, int option);

#endif /* __POWERNV_PCI_H */

0 comments on commit 361f2a2

Please sign in to comment.