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:
Michael S. Tsirkin 2010-11-17 15:45:39 +02:00
parent 247c97f3f5
commit d33d9156fd
1 changed files with 30 additions and 56 deletions

View File

@ -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);
}
}