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 <mst@redhat.com>
This commit is contained in:
		
							parent
							
								
									247c97f3f5
								
							
						
					
					
						commit
						d33d9156fd
					
				| 
						 | 
				
			
			@ -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);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue