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;
|
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:
|
* return value:
|
||||||
* true: error message is sent up
|
* 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
|
* 6.2.6 Error Message Control Figure 6-3
|
||||||
*
|
*
|
||||||
* Returns true in case the error needs to
|
* Walk up the bus tree from the device, propagate the error message.
|
||||||
* be propagated up.
|
|
||||||
* TODO: open-code.
|
|
||||||
*/
|
*/
|
||||||
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)
|
static void pcie_aer_msg(PCIDevice *dev, const PCIEAERMsg *msg)
|
||||||
{
|
{
|
||||||
bool send_to_parent;
|
uint8_t type;
|
||||||
|
|
||||||
while (dev) {
|
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;
|
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