2009年3月27日 星期五

Linux PCI Error Recovery

Documentation/PCI/pci-error-recovery.txt

link_rest沒人用,倒是系統有提供一個reset_link

include/linux/pci.h

/* PCI bus error event callbacks */
struct pci_error_handlers {
/* PCI bus error detected on this device */
pci_ers_result_t (*error_detected)(struct pci_dev *dev,
enum pci_channel_state error);

/* MMIO has been re-enabled, but not DMA */
pci_ers_result_t (*mmio_enabled)(struct pci_dev *dev);

/* PCI Express link has been reset */
pci_ers_result_t (* link_reset)(struct pci_dev *dev);

/* PCI slot has been reset */
pci_ers_result_t (*slot_reset)(struct pci_dev *dev);

/* Device driver may resume normal operations */
void (*resume)(struct pci_dev *dev);
};


drivers/pci/pcie/aer/aerdrv_core.c
/**
* do_recovery - handle nonfatal/fatal error recovery process
* @aerdev: pointer to a pcie_device data structure of root port
* @dev: pointer to a pci_dev data structure of agent detecting an error
* @severity: error severity type
*
* Invoked when an error is nonfatal/fatal. Once being invoked, broadcast
* error detected message to all downstream drivers within a hierarchy in
* question and return the returned code.
*/
static pci_ers_result_t do_recovery(struct pcie_device *aerdev,
struct pci_dev *dev,
int severity)
{
pci_ers_result_t status, result = PCI_ERS_RESULT_RECOVERED;
enum pci_channel_state state;

if (severity == AER_FATAL)
state = pci_channel_io_frozen;
else
state = pci_channel_io_normal;

status = broadcast_error_message(dev,
state,
"error_detected",
report_error_detected);

if (severity == AER_FATAL) {
result = reset_link(aerdev, dev);
if (result != PCI_ERS_RESULT_RECOVERED) {
/* TODO: Should panic here? */
return result;
}
}

if (status == PCI_ERS_RESULT_CAN_RECOVER)
status = broadcast_error_message(dev,
state,
"mmio_enabled",
report_mmio_enabled);

if (status == PCI_ERS_RESULT_NEED_RESET) {
/*
* TODO: Should call platform-specific
* functions to reset slot before calling
* drivers' slot_reset callbacks?
*/
status = broadcast_error_message(dev,
state,
"slot_reset",
report_slot_reset);
}

if (status == PCI_ERS_RESULT_RECOVERED)
broadcast_error_message(dev,
state,
"resume",
report_resume);

return status;
}

沒有留言: