... and rebase pci_add_capability() to it. Signed-off-by: Laszlo Ersek <ler...@redhat.com> --- include/hw/pci/pci.h | 4 ++++ hw/pci/pci.c | 32 ++++++++++++++++++++++++++------ 2 files changed, 30 insertions(+), 6 deletions(-)
diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h index 693dd6b..8c25ae5 100644 --- a/include/hw/pci/pci.h +++ b/include/hw/pci/pci.h @@ -4,10 +4,11 @@ #include "qemu-common.h" #include "hw/qdev.h" #include "exec/memory.h" #include "sysemu/dma.h" +#include "qapi/error.h" /* PCI includes legacy ISA access. */ #include "hw/isa/isa.h" #include "hw/pci/pcie.h" @@ -306,10 +307,13 @@ void pci_register_vga(PCIDevice *pci_dev, MemoryRegion *mem, void pci_unregister_vga(PCIDevice *pci_dev); pcibus_t pci_get_bar_addr(PCIDevice *pci_dev, int region_num); int pci_add_capability(PCIDevice *pdev, uint8_t cap_id, uint8_t offset, uint8_t size); +int pci_add_capability2(PCIDevice *pdev, uint8_t cap_id, + uint8_t offset, uint8_t size, + Error **errp); void pci_del_capability(PCIDevice *pci_dev, uint8_t cap_id, uint8_t cap_size); uint8_t pci_find_capability(PCIDevice *pci_dev, uint8_t cap_id); diff --git a/hw/pci/pci.c b/hw/pci/pci.c index 2a9f08e..64e6f23 100644 --- a/hw/pci/pci.c +++ b/hw/pci/pci.c @@ -2011,32 +2011,52 @@ static void pci_del_option_rom(PCIDevice *pdev) * Find and reserve space and add capability to the linked list * in pci config space */ int pci_add_capability(PCIDevice *pdev, uint8_t cap_id, uint8_t offset, uint8_t size) { + int ret; + Error *local_err = NULL; + + ret = pci_add_capability2(pdev, cap_id, offset, size, &local_err); + if (local_err) { + assert(ret < 0); + error_report("%s", error_get_pretty(local_err)); + error_free(local_err); + } else { + /* success implies a positive offset in config space */ + assert(ret > 0); + } + return ret; +} + +int pci_add_capability2(PCIDevice *pdev, uint8_t cap_id, + uint8_t offset, uint8_t size, + Error **errp) +{ uint8_t *config; int i, overlapping_cap; if (!offset) { offset = pci_find_space(pdev, size); if (!offset) { + error_setg(errp, "out of PCI config space"); return -ENOSPC; } } else { /* Verify that capabilities don't overlap. Note: device assignment * depends on this check to verify that the device is not broken. * Should never trigger for emulated devices, but it's helpful * for debugging these. */ for (i = offset; i < offset + size; i++) { overlapping_cap = pci_find_capability_at_offset(pdev, i); if (overlapping_cap) { - fprintf(stderr, "ERROR: %s:%02x:%02x.%x " - "Attempt to add PCI capability %x at offset " - "%x overlaps existing capability %x at offset %x\n", - pci_root_bus_path(pdev), pci_bus_num(pdev->bus), - PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn), - cap_id, offset, overlapping_cap, i); + error_setg(errp, "%s:%02x:%02x.%x " + "Attempt to add PCI capability %x at offset " + "%x overlaps existing capability %x at offset %x", + pci_root_bus_path(pdev), pci_bus_num(pdev->bus), + PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn), + cap_id, offset, overlapping_cap, i); return -EINVAL; } } } -- 1.8.3.1