Revision d33d9156
b/hw/pcie_aer.c | ||
---|---|---|
215 | 215 |
return true; |
216 | 216 |
} |
217 | 217 |
|
218 |
/* Get parent port to send up error message on. |
|
219 |
* TODO: clean up and open-code this logic */ |
|
220 |
static PCIDevice *pcie_aer_parent_port(PCIDevice *dev) |
|
221 |
{ |
|
222 |
PCIDevice *parent_port; |
|
223 |
if (pci_is_express(dev) && |
|
224 |
pcie_cap_get_type(dev) == PCI_EXP_TYPE_ROOT_PORT) { |
|
225 |
/* Root port can notify system itself, |
|
226 |
or send the error message to root complex event collector. */ |
|
227 |
/* |
|
228 |
* if root port is associated with an event collector, |
|
229 |
* return the root complex event collector here. |
|
230 |
* For now root complex event collector isn't supported. |
|
231 |
*/ |
|
232 |
parent_port = NULL; |
|
233 |
} else { |
|
234 |
parent_port = pci_bridge_get_device(dev->bus); |
|
235 |
} |
|
236 |
if (parent_port) { |
|
237 |
if (!pci_is_express(parent_port)) { |
|
238 |
/* just ignore it */ |
|
239 |
return NULL; |
|
240 |
} |
|
241 |
} |
|
242 |
return parent_port; |
|
243 |
} |
|
244 |
|
|
245 | 218 |
/* |
246 | 219 |
* return value: |
247 | 220 |
* true: error message is sent up |
... | ... | |
381 | 354 |
/* |
382 | 355 |
* 6.2.6 Error Message Control Figure 6-3 |
383 | 356 |
* |
384 |
* Returns true in case the error needs to |
|
385 |
* be propagated up. |
|
386 |
* TODO: open-code. |
|
357 |
* Walk up the bus tree from the device, propagate the error message. |
|
387 | 358 |
*/ |
388 |
static bool pcie_send_aer_msg(PCIDevice *dev, const PCIEAERMsg *msg)
|
|
359 |
static void pcie_aer_msg(PCIDevice *dev, const PCIEAERMsg *msg)
|
|
389 | 360 |
{ |
390 | 361 |
uint8_t type; |
391 |
bool msg_sent; |
|
392 |
|
|
393 |
assert(pci_is_express(dev)); |
|
394 | 362 |
|
395 |
type = pcie_cap_get_type(dev); |
|
396 |
if (type == PCI_EXP_TYPE_ROOT_PORT || |
|
397 |
type == PCI_EXP_TYPE_UPSTREAM || |
|
398 |
type == PCI_EXP_TYPE_DOWNSTREAM) { |
|
399 |
msg_sent = pcie_aer_msg_vbridge(dev, msg); |
|
400 |
if (!msg_sent) { |
|
363 |
while (dev) { |
|
364 |
if (!pci_is_express(dev)) { |
|
365 |
/* just ignore it */ |
|
366 |
/* TODO: Shouldn't we set PCI_STATUS_SIG_SYSTEM_ERROR? |
|
367 |
* Consider e.g. a PCI bridge above a PCI Express device. */ |
|
401 | 368 |
return; |
402 | 369 |
} |
403 |
} |
|
404 |
msg_sent = pcie_aer_msg_alldev(dev, msg); |
|
405 |
if (type == PCI_EXP_TYPE_ROOT_PORT && msg_sent) { |
|
406 |
pcie_aer_msg_root_port(dev, msg); |
|
407 |
} |
|
408 |
return msg_sent; |
|
409 |
} |
|
410 | 370 |
|
411 |
static void pcie_aer_msg(PCIDevice *dev, const PCIEAERMsg *msg) |
|
412 |
{ |
|
413 |
bool send_to_parent; |
|
414 |
while (dev) { |
|
415 |
if (!pcie_send_aer_msg(dev, msg)) { |
|
371 |
type = pcie_cap_get_type(dev); |
|
372 |
if ((type == PCI_EXP_TYPE_ROOT_PORT || |
|
373 |
type == PCI_EXP_TYPE_UPSTREAM || |
|
374 |
type == PCI_EXP_TYPE_DOWNSTREAM) && |
|
375 |
!pcie_aer_msg_vbridge(dev, msg)) { |
|
376 |
return; |
|
377 |
} |
|
378 |
if (!pcie_aer_msg_alldev(dev, msg)) { |
|
379 |
return; |
|
380 |
} |
|
381 |
if (type == PCI_EXP_TYPE_ROOT_PORT) { |
|
382 |
pcie_aer_msg_root_port(dev, msg); |
|
383 |
/* Root port can notify system itself, |
|
384 |
or send the error message to root complex event collector. */ |
|
385 |
/* |
|
386 |
* if root port is associated with an event collector, |
|
387 |
* return the root complex event collector here. |
|
388 |
* For now root complex event collector isn't supported. |
|
389 |
*/ |
|
416 | 390 |
return; |
417 | 391 |
} |
418 |
dev = pcie_aer_parent_port(dev);
|
|
392 |
dev = pci_bridge_get_device(dev->bus);
|
|
419 | 393 |
} |
420 | 394 |
} |
421 | 395 |
|
Also available in: Unified diff