From d33d9156fdffb87c99564c9630023da52c66f37a Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Wed, 17 Nov 2010 15:45:39 +0200 Subject: [PATCH] pcie_aer: complete unwinding recursion Open-code functions created in the previous patch, to make code more compact and clear. Detcted and documented what looks like a bug in code that becomes apparent from this refactoring. Signed-off-by: Michael S. Tsirkin --- hw/pcie_aer.c | 86 ++++++++++++++++++--------------------------------- 1 file changed, 30 insertions(+), 56 deletions(-) diff --git a/hw/pcie_aer.c b/hw/pcie_aer.c index c565d393d..235ac534d 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) -{ - 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) { - 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; + uint8_t type; + while (dev) { - if (!pcie_send_aer_msg(dev, msg)) { + 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; } - dev = pcie_aer_parent_port(dev); + + 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 = pci_bridge_get_device(dev->bus); } }