Commit d33d9156 authored by Michael S. Tsirkin's avatar Michael S. Tsirkin
Browse files

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: default avatarMichael S. Tsirkin <mst@redhat.com>
parent 247c97f3
Loading
Loading
Loading
Loading
+27 −53
Original line number Diff line number Diff line
@@ -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));
    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;
        }

        type = pcie_cap_get_type(dev);
    if (type == PCI_EXP_TYPE_ROOT_PORT ||
        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) {
            type == PCI_EXP_TYPE_DOWNSTREAM) &&
            !pcie_aer_msg_vbridge(dev, msg)) {
                return;
        }
        if (!pcie_aer_msg_alldev(dev, msg)) {
            return;
        }
    msg_sent = pcie_aer_msg_alldev(dev, msg);
    if (type == PCI_EXP_TYPE_ROOT_PORT && msg_sent) {
        if (type == PCI_EXP_TYPE_ROOT_PORT) {
            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)) {
            /* 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);
    }
}