/* Content Code Description for PCI Function Error */ struct zpci_ccdf_err {
u32 reserved1;
u32 fh; /* function handle */
u32 fid; /* function id */
u32 ett : 4; /* expected table type */
u32 mvn : 12; /* MSI vector number */
u32 dmaas : 8; /* DMA address space */
u32 : 6;
u32 q : 1; /* event qualifier */
u32 rw : 1; /* read/write */
u64 faddr; /* failing address */
u32 reserved3;
u16 reserved4;
u16 pec; /* PCI event code */
} __packed;
/* Content Code Description for PCI Function Availability */ struct zpci_ccdf_avail {
u32 reserved1;
u32 fh; /* function handle */
u32 fid; /* function id */
u32 reserved2;
u32 reserved3;
u32 reserved4;
u32 reserved5;
u16 reserved6;
u16 pec; /* PCI event code */
} __packed;
staticinlinebool ers_result_indicates_abort(pci_ers_result_t ers_res)
{ switch (ers_res) { case PCI_ERS_RESULT_CAN_RECOVER: case PCI_ERS_RESULT_RECOVERED: case PCI_ERS_RESULT_NEED_RESET: case PCI_ERS_RESULT_NONE: returnfalse; default: returntrue;
}
}
if (is_passed_through(pdev)) {
pr_info("%s: Cannot be recovered in the host because it is a pass-through device\n",
pci_name(pdev));
status_str = "failed (pass-through)"; goto out_unlock;
}
driver = to_pci_driver(pdev->dev.driver); if (!is_driver_supported(driver)) { if (!driver) {
pr_info("%s: Cannot be recovered because no driver is bound to the device\n",
pci_name(pdev));
status_str = "failed (no driver)";
} else {
pr_info("%s: The %s driver bound to the device does not support error recovery\n",
pci_name(pdev),
driver->name);
status_str = "failed (no driver support)";
} goto out_unlock;
}
ers_res = zpci_event_notify_error_detected(pdev, driver); if (ers_result_indicates_abort(ers_res)) {
status_str = "failed (abort on detection)"; goto out_unlock;
}
if (ers_res != PCI_ERS_RESULT_NEED_RESET) {
ers_res = zpci_event_do_error_state_clear(pdev, driver); if (ers_result_indicates_abort(ers_res)) {
status_str = "failed (abort on MMIO enable)"; goto out_unlock;
}
}
if (ers_res == PCI_ERS_RESULT_NEED_RESET)
ers_res = zpci_event_do_reset(pdev, driver);
pr_info("%s: The device is ready to resume operations\n", pci_name(pdev)); if (driver->err_handler->resume)
driver->err_handler->resume(pdev);
pci_uevent_ers(pdev, PCI_ERS_RESULT_RECOVERED);
out_unlock:
device_unlock(&pdev->dev);
zpci_report_status(zdev, "recovery", status_str);
if (zdev) {
mutex_lock(&zdev->state_lock);
rc = clp_refresh_fh(zdev->fid, &fh); if (rc) goto no_pdev; if (!fh || ccdf->fh != fh) { /* Ignore events with stale handles */
zpci_dbg(3, "err fid:%x, fh:%x (stale %x)\n",
ccdf->fid, fh, ccdf->fh); goto no_pdev;
}
zpci_update_fh(zdev, ccdf->fh); if (zdev->zbus->bus)
pdev = pci_get_slot(zdev->zbus->bus, zdev->devfn);
}
pr_err("%s: Event 0x%x reports an error for PCI function 0x%x\n",
pdev ? pci_name(pdev) : "n/a", ccdf->pec, ccdf->fid);
if (!pdev) goto no_pdev;
switch (ccdf->pec) { case0x002a: /* Error event concerns FMB */ case0x002b: case0x002c: break; case0x0040: /* Service Action or Error Recovery Failed */ case0x003b:
zpci_event_io_failure(pdev, pci_channel_io_perm_failure); break; default: /* PCI function left in the error state attempt to recover */
ers_res = zpci_event_attempt_error_recovery(pdev); if (ers_res != PCI_ERS_RESULT_RECOVERED)
zpci_event_io_failure(pdev, pci_channel_io_perm_failure); break;
}
pci_dev_put(pdev);
no_pdev: if (zdev)
mutex_unlock(&zdev->state_lock);
zpci_zdev_put(zdev);
}
void zpci_event_error(void *data)
{ if (zpci_is_enabled())
__zpci_event_error(data);
}
staticvoid zpci_event_hard_deconfigured(struct zpci_dev *zdev, u32 fh)
{
zpci_update_fh(zdev, fh); /* Give the driver a hint that the function is *alreadyunusable.
*/
zpci_bus_remove_device(zdev, true); /* Even though the device is already gone we still *needtofreezPCIresourcesaspartofthedisable.
*/ if (zdev_enabled(zdev))
zpci_disable_device(zdev);
zdev->state = ZPCI_FN_STATE_STANDBY;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.