|
@@ -337,43 +337,52 @@ void pnv_pci_dump_phb_diag_data(struct pci_controller *hose,
|
|
|
static void pnv_pci_handle_eeh_config(struct pnv_phb *phb, u32 pe_no)
|
|
|
{
|
|
|
unsigned long flags, rc;
|
|
|
- int has_diag;
|
|
|
+ int has_diag, ret = 0;
|
|
|
|
|
|
spin_lock_irqsave(&phb->lock, flags);
|
|
|
|
|
|
+ /* Fetch PHB diag-data */
|
|
|
rc = opal_pci_get_phb_diag_data2(phb->opal_id, phb->diag.blob,
|
|
|
PNV_PCI_DIAG_BUF_SIZE);
|
|
|
has_diag = (rc == OPAL_SUCCESS);
|
|
|
|
|
|
- rc = opal_pci_eeh_freeze_clear(phb->opal_id, pe_no,
|
|
|
+ /* If PHB supports compound PE, to handle it */
|
|
|
+ if (phb->unfreeze_pe) {
|
|
|
+ ret = phb->unfreeze_pe(phb,
|
|
|
+ pe_no,
|
|
|
OPAL_EEH_ACTION_CLEAR_FREEZE_ALL);
|
|
|
- if (rc) {
|
|
|
- pr_warning("PCI %d: Failed to clear EEH freeze state"
|
|
|
- " for PE#%d, err %ld\n",
|
|
|
- phb->hose->global_number, pe_no, rc);
|
|
|
-
|
|
|
- /* For now, let's only display the diag buffer when we fail to clear
|
|
|
- * the EEH status. We'll do more sensible things later when we have
|
|
|
- * proper EEH support. We need to make sure we don't pollute ourselves
|
|
|
- * with the normal errors generated when probing empty slots
|
|
|
- */
|
|
|
- if (has_diag)
|
|
|
- pnv_pci_dump_phb_diag_data(phb->hose, phb->diag.blob);
|
|
|
- else
|
|
|
- pr_warning("PCI %d: No diag data available\n",
|
|
|
- phb->hose->global_number);
|
|
|
+ } else {
|
|
|
+ rc = opal_pci_eeh_freeze_clear(phb->opal_id,
|
|
|
+ pe_no,
|
|
|
+ OPAL_EEH_ACTION_CLEAR_FREEZE_ALL);
|
|
|
+ if (rc) {
|
|
|
+ pr_warn("%s: Failure %ld clearing frozen "
|
|
|
+ "PHB#%x-PE#%x\n",
|
|
|
+ __func__, rc, phb->hose->global_number,
|
|
|
+ pe_no);
|
|
|
+ ret = -EIO;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
+ /*
|
|
|
+ * For now, let's only display the diag buffer when we fail to clear
|
|
|
+ * the EEH status. We'll do more sensible things later when we have
|
|
|
+ * proper EEH support. We need to make sure we don't pollute ourselves
|
|
|
+ * with the normal errors generated when probing empty slots
|
|
|
+ */
|
|
|
+ if (has_diag && ret)
|
|
|
+ pnv_pci_dump_phb_diag_data(phb->hose, phb->diag.blob);
|
|
|
+
|
|
|
spin_unlock_irqrestore(&phb->lock, flags);
|
|
|
}
|
|
|
|
|
|
static void pnv_pci_config_check_eeh(struct pnv_phb *phb,
|
|
|
struct device_node *dn)
|
|
|
{
|
|
|
- s64 rc;
|
|
|
u8 fstate;
|
|
|
__be16 pcierr;
|
|
|
- u32 pe_no;
|
|
|
+ int pe_no;
|
|
|
+ s64 rc;
|
|
|
|
|
|
/*
|
|
|
* Get the PE#. During the PCI probe stage, we might not
|
|
@@ -388,20 +397,42 @@ static void pnv_pci_config_check_eeh(struct pnv_phb *phb,
|
|
|
pe_no = phb->ioda.reserved_pe;
|
|
|
}
|
|
|
|
|
|
- /* Read freeze status */
|
|
|
- rc = opal_pci_eeh_freeze_status(phb->opal_id, pe_no, &fstate, &pcierr,
|
|
|
- NULL);
|
|
|
- if (rc) {
|
|
|
- pr_warning("%s: Can't read EEH status (PE#%d) for "
|
|
|
- "%s, err %lld\n",
|
|
|
- __func__, pe_no, dn->full_name, rc);
|
|
|
- return;
|
|
|
+ /*
|
|
|
+ * Fetch frozen state. If the PHB support compound PE,
|
|
|
+ * we need handle that case.
|
|
|
+ */
|
|
|
+ if (phb->get_pe_state) {
|
|
|
+ fstate = phb->get_pe_state(phb, pe_no);
|
|
|
+ } else {
|
|
|
+ rc = opal_pci_eeh_freeze_status(phb->opal_id,
|
|
|
+ pe_no,
|
|
|
+ &fstate,
|
|
|
+ &pcierr,
|
|
|
+ NULL);
|
|
|
+ if (rc) {
|
|
|
+ pr_warn("%s: Failure %lld getting PHB#%x-PE#%x state\n",
|
|
|
+ __func__, rc, phb->hose->global_number, pe_no);
|
|
|
+ return;
|
|
|
+ }
|
|
|
}
|
|
|
+
|
|
|
cfg_dbg(" -> EEH check, bdfn=%04x PE#%d fstate=%x\n",
|
|
|
(PCI_DN(dn)->busno << 8) | (PCI_DN(dn)->devfn),
|
|
|
pe_no, fstate);
|
|
|
- if (fstate != 0)
|
|
|
+
|
|
|
+ /* Clear the frozen state if applicable */
|
|
|
+ if (fstate == OPAL_EEH_STOPPED_MMIO_FREEZE ||
|
|
|
+ fstate == OPAL_EEH_STOPPED_DMA_FREEZE ||
|
|
|
+ fstate == OPAL_EEH_STOPPED_MMIO_DMA_FREEZE) {
|
|
|
+ /*
|
|
|
+ * If PHB supports compound PE, freeze it for
|
|
|
+ * consistency.
|
|
|
+ */
|
|
|
+ if (phb->freeze_pe)
|
|
|
+ phb->freeze_pe(phb, pe_no);
|
|
|
+
|
|
|
pnv_pci_handle_eeh_config(phb, pe_no);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
int pnv_pci_cfg_read(struct device_node *dn,
|