diff options
-rw-r--r-- | hw/pcie_aer.c | 80 |
1 files changed, 27 insertions, 53 deletions
diff --git a/hw/pcie_aer.c b/hw/pcie_aer.c index c565d393d6..235ac534d7 100644 --- a/hw/pcie_aer.c +++ b/hw/pcie_aer.c @@ -215,33 +215,6 @@ pcie_aer_msg_alldev(PCIDevice *dev, const PCIEAERMsg *msg) return true; } -/* Get parent port to send up error message on. - * TODO: clean up and open-code this logic */ -static PCIDevice *pcie_aer_parent_port(PCIDevice *dev) -{ - PCIDevice *parent_port; - if (pci_is_express(dev) && - pcie_cap_get_type(dev) == PCI_EXP_TYPE_ROOT_PORT) { - /* Root port can notify system itself, - or send the error message to root complex event collector. */ - /* - * if root port is associated with an event collector, - * return the root complex event collector here. - * For now root complex event collector isn't supported. - */ - parent_port = NULL; - } else { - parent_port = pci_bridge_get_device(dev->bus); - } - if (parent_port) { - if (!pci_is_express(parent_port)) { - /* just ignore it */ - return NULL; - } - } - return parent_port; -} - /* * return value: * true: error message is sent up @@ -381,41 +354,42 @@ static bool pcie_aer_msg_root_port(PCIDevice *dev, const PCIEAERMsg *msg) /* * 6.2.6 Error Message Control Figure 6-3 * - * Returns true in case the error needs to - * be propagated up. - * TODO: open-code. + * Walk up the bus tree from the device, propagate the error message. */ -static bool pcie_send_aer_msg(PCIDevice *dev, const PCIEAERMsg *msg) +static void pcie_aer_msg(PCIDevice *dev, const PCIEAERMsg *msg) { uint8_t type; - bool msg_sent; - - assert(pci_is_express(dev)); - type = pcie_cap_get_type(dev); - if (type == PCI_EXP_TYPE_ROOT_PORT || - type == PCI_EXP_TYPE_UPSTREAM || - type == PCI_EXP_TYPE_DOWNSTREAM) { - msg_sent = pcie_aer_msg_vbridge(dev, msg); - if (!msg_sent) { + while (dev) { + if (!pci_is_express(dev)) { + /* just ignore it */ + /* TODO: Shouldn't we set PCI_STATUS_SIG_SYSTEM_ERROR? + * Consider e.g. a PCI bridge above a PCI Express device. */ return; } - } - msg_sent = pcie_aer_msg_alldev(dev, msg); - if (type == PCI_EXP_TYPE_ROOT_PORT && msg_sent) { - pcie_aer_msg_root_port(dev, msg); - } - return msg_sent; -} -static void pcie_aer_msg(PCIDevice *dev, const PCIEAERMsg *msg) -{ - bool send_to_parent; - while (dev) { - if (!pcie_send_aer_msg(dev, msg)) { + type = pcie_cap_get_type(dev); + if ((type == PCI_EXP_TYPE_ROOT_PORT || + type == PCI_EXP_TYPE_UPSTREAM || + type == PCI_EXP_TYPE_DOWNSTREAM) && + !pcie_aer_msg_vbridge(dev, msg)) { + return; + } + if (!pcie_aer_msg_alldev(dev, msg)) { + return; + } + if (type == PCI_EXP_TYPE_ROOT_PORT) { + pcie_aer_msg_root_port(dev, msg); + /* Root port can notify system itself, + or send the error message to root complex event collector. */ + /* + * if root port is associated with an event collector, + * return the root complex event collector here. + * For now root complex event collector isn't supported. + */ return; } - dev = pcie_aer_parent_port(dev); + dev = pci_bridge_get_device(dev->bus); } } |