diff options
| author | Anthony Liguori <aliguori@us.ibm.com> | 2012-07-30 10:00:48 -0500 |
|---|---|---|
| committer | Anthony Liguori <aliguori@us.ibm.com> | 2012-07-30 10:00:48 -0500 |
| commit | 5e3bc7144edd6e4fa2824944e5eb16c28197dd5a (patch) | |
| tree | e12e9145e74916485b482b2336bf1775a177e635 /hw/pci.c | |
| parent | 4dd533aa03d6844f61e95558d75d8dbec72d899c (diff) | |
| parent | 5e59b024351f827f903f98ae522687ea53dc4f23 (diff) | |
| download | focaccia-qemu-5e3bc7144edd6e4fa2824944e5eb16c28197dd5a.tar.gz focaccia-qemu-5e3bc7144edd6e4fa2824944e5eb16c28197dd5a.zip | |
Merge remote-tracking branch 'mst/tags/for_anthony' into staging
* mst/tags/for_anthony: msi/msix: added API to set MSI message address and data pci: Add INTx routing notifier pci: Add pci_device_route_intx_to_irq pci: Unregister BARs before device exit pci: convert PCIUnregisterFunc to void msix: Switch msix_uninit to return void msix: Allow full specification of MSIX layout msix: Split PBA into it's own MemoryRegion msix: Note endian TODO item msix: Move msix_mmio_read virtio: Convert to msix_init_exclusive_bar() interface ivshmem: Convert to msix_init_exclusive_bar() interface msix: Add simple BAR allocation MSIX setup functions msix: fix PCIDevice naming inconsistency msix: drop unused msix_bar_size, require valid bar_size
Diffstat (limited to 'hw/pci.c')
| -rw-r--r-- | hw/pci.c | 54 |
1 files changed, 48 insertions, 6 deletions
diff --git a/hw/pci.c b/hw/pci.c index 99a43041dd..4d95984807 100644 --- a/hw/pci.c +++ b/hw/pci.c @@ -849,15 +849,14 @@ static int pci_unregister_device(DeviceState *dev) { PCIDevice *pci_dev = PCI_DEVICE(dev); PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(pci_dev); - int ret = 0; - - if (pc->exit) - ret = pc->exit(pci_dev); - if (ret) - return ret; pci_unregister_io_regions(pci_dev); pci_del_option_rom(pci_dev); + + if (pc->exit) { + pc->exit(pci_dev); + } + do_pci_unregister_device(pci_dev); return 0; } @@ -1079,6 +1078,49 @@ static void pci_set_irq(void *opaque, int irq_num, int level) pci_change_irq_level(pci_dev, irq_num, change); } +/* Special hooks used by device assignment */ +void pci_bus_set_route_irq_fn(PCIBus *bus, pci_route_irq_fn route_intx_to_irq) +{ + assert(!bus->parent_dev); + bus->route_intx_to_irq = route_intx_to_irq; +} + +PCIINTxRoute pci_device_route_intx_to_irq(PCIDevice *dev, int pin) +{ + PCIBus *bus; + + do { + bus = dev->bus; + pin = bus->map_irq(dev, pin); + dev = bus->parent_dev; + } while (dev); + assert(bus->route_intx_to_irq); + return bus->route_intx_to_irq(bus->irq_opaque, pin); +} + +void pci_bus_fire_intx_routing_notifier(PCIBus *bus) +{ + PCIDevice *dev; + PCIBus *sec; + int i; + + for (i = 0; i < ARRAY_SIZE(bus->devices); ++i) { + dev = bus->devices[i]; + if (dev && dev->intx_routing_notifier) { + dev->intx_routing_notifier(dev); + } + QLIST_FOREACH(sec, &bus->child, sibling) { + pci_bus_fire_intx_routing_notifier(sec); + } + } +} + +void pci_device_set_intx_routing_notifier(PCIDevice *dev, + PCIINTxRoutingNotifier notifier) +{ + dev->intx_routing_notifier = notifier; +} + /***********************************************************/ /* monitor info on PCI */ |