diff options
author | Anthony Liguori <aliguori@us.ibm.com> | 2012-06-18 10:18:44 -0500 |
---|---|---|
committer | Anthony Liguori <aliguori@us.ibm.com> | 2012-06-18 10:18:44 -0500 |
commit | df6606f4556a752d30a4eab26c626b6c34717ea8 (patch) | |
tree | 095df894fd2f1e40f6a8a5a6393e10a953d8054d /hw | |
parent | 49023ff78cf1efeb861b475c40dd04262efe61d3 (diff) | |
parent | 80aa796bf38b7ef21daa42673b4711510c450d8a (diff) |
Merge remote-tracking branch 'mst/tags/for_anthony' into staging
* mst/tags/for_anthony:
pci_bridge_dev: fix error path in pci_bridge_dev_initfn()
qdev: release parent properties on dc->init failure
msi: Use msi/msix_present more consistently
msi: Invoke msi/msix_write_config from PCI core
msi: Guard msi/msix_write_config with msi_present
msi: Invoke msi/msix_reset from PCI core
msi: Guard msi_reset with msi_present
ahci: Clean up reset functions
intel-hda: Fix reset of MSI function
ahci: Fix reset of MSI function
rtl8139: honor RxOverflow flag in can_receive method
shpc: unparent device before free
Diffstat (limited to 'hw')
-rw-r--r-- | hw/ide/ahci.c | 25 | ||||
-rw-r--r-- | hw/ide/ahci.h | 2 | ||||
-rw-r--r-- | hw/ide/ich.c | 19 | ||||
-rw-r--r-- | hw/intel-hda.c | 12 | ||||
-rw-r--r-- | hw/ioh3420.c | 3 | ||||
-rw-r--r-- | hw/ivshmem.c | 1 | ||||
-rw-r--r-- | hw/msi.c | 11 | ||||
-rw-r--r-- | hw/msix.c | 15 | ||||
-rw-r--r-- | hw/pci.c | 8 | ||||
-rw-r--r-- | hw/pci_bridge.c | 10 | ||||
-rw-r--r-- | hw/pci_bridge_dev.c | 8 | ||||
-rw-r--r-- | hw/qdev.c | 1 | ||||
-rw-r--r-- | hw/rtl8139.c | 2 | ||||
-rw-r--r-- | hw/shpc.c | 1 | ||||
-rw-r--r-- | hw/virtio-pci.c | 3 | ||||
-rw-r--r-- | hw/xio3130_downstream.c | 3 | ||||
-rw-r--r-- | hw/xio3130_upstream.c | 3 |
17 files changed, 61 insertions, 66 deletions
diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c index 2d7d03d772..e275e68934 100644 --- a/hw/ide/ahci.c +++ b/hw/ide/ahci.c @@ -339,7 +339,7 @@ static void ahci_mem_write(void *opaque, target_phys_addr_t addr, case HOST_CTL: /* R/W */ if (val & HOST_CTL_RESET) { DPRINTF(-1, "HBA Reset\n"); - ahci_reset(container_of(s, AHCIPCIState, ahci)); + ahci_reset(s); } else { s->control_regs.ghc = (val & 0x3) | HOST_CTL_AHCI_EN; ahci_check_irq(s); @@ -1149,21 +1149,20 @@ void ahci_uninit(AHCIState *s) g_free(s->dev); } -void ahci_reset(void *opaque) +void ahci_reset(AHCIState *s) { - struct AHCIPCIState *d = opaque; AHCIPortRegs *pr; int i; - d->ahci.control_regs.irqstatus = 0; - d->ahci.control_regs.ghc = 0; + s->control_regs.irqstatus = 0; + s->control_regs.ghc = 0; - for (i = 0; i < d->ahci.ports; i++) { - pr = &d->ahci.dev[i].port_regs; + for (i = 0; i < s->ports; i++) { + pr = &s->dev[i].port_regs; pr->irq_stat = 0; pr->irq_mask = 0; pr->scr_ctl = 0; - ahci_reset_port(&d->ahci, i); + ahci_reset_port(s, i); } } @@ -1178,6 +1177,13 @@ static const VMStateDescription vmstate_sysbus_ahci = { .unmigratable = 1, }; +static void sysbus_ahci_reset(DeviceState *dev) +{ + SysbusAHCIState *s = DO_UPCAST(SysbusAHCIState, busdev.qdev, dev); + + ahci_reset(&s->ahci); +} + static int sysbus_ahci_init(SysBusDevice *dev) { SysbusAHCIState *s = FROM_SYSBUS(SysbusAHCIState, dev); @@ -1185,8 +1191,6 @@ static int sysbus_ahci_init(SysBusDevice *dev) sysbus_init_mmio(dev, &s->ahci.mem); sysbus_init_irq(dev, &s->ahci.irq); - - qemu_register_reset(ahci_reset, &s->ahci); return 0; } @@ -1203,6 +1207,7 @@ static void sysbus_ahci_class_init(ObjectClass *klass, void *data) sbc->init = sysbus_ahci_init; dc->vmsd = &vmstate_sysbus_ahci; dc->props = sysbus_ahci_properties; + dc->reset = sysbus_ahci_reset; } static TypeInfo sysbus_ahci_info = { diff --git a/hw/ide/ahci.h b/hw/ide/ahci.h index b223d2c055..ec1b6a5f66 100644 --- a/hw/ide/ahci.h +++ b/hw/ide/ahci.h @@ -332,6 +332,6 @@ typedef struct NCQFrame { void ahci_init(AHCIState *s, DeviceState *qdev, int ports); void ahci_uninit(AHCIState *s); -void ahci_reset(void *opaque); +void ahci_reset(AHCIState *s); #endif /* HW_IDE_AHCI_H */ diff --git a/hw/ide/ich.c b/hw/ide/ich.c index 560ae37618..e3eaaea882 100644 --- a/hw/ide/ich.c +++ b/hw/ide/ich.c @@ -84,6 +84,13 @@ static const VMStateDescription vmstate_ahci = { .unmigratable = 1, }; +static void pci_ich9_reset(DeviceState *dev) +{ + struct AHCIPCIState *d = DO_UPCAST(struct AHCIPCIState, card.qdev, dev); + + ahci_reset(&d->ahci); +} + static int pci_ich9_ahci_init(PCIDevice *dev) { struct AHCIPCIState *d; @@ -102,8 +109,6 @@ static int pci_ich9_ahci_init(PCIDevice *dev) /* XXX Software should program this register */ d->card.config[0x90] = 1 << 6; /* Address Map Register - AHCI mode */ - qemu_register_reset(ahci_reset, d); - msi_init(dev, 0x50, 1, true, false); d->ahci.irq = d->card.irq[0]; @@ -133,19 +138,11 @@ static int pci_ich9_uninit(PCIDevice *dev) d = DO_UPCAST(struct AHCIPCIState, card, dev); msi_uninit(dev); - qemu_unregister_reset(ahci_reset, d); ahci_uninit(&d->ahci); return 0; } -static void pci_ich9_write_config(PCIDevice *pci, uint32_t addr, - uint32_t val, int len) -{ - pci_default_write_config(pci, addr, val, len); - msi_write_config(pci, addr, val, len); -} - static void ich_ahci_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); @@ -153,12 +150,12 @@ static void ich_ahci_class_init(ObjectClass *klass, void *data) k->init = pci_ich9_ahci_init; k->exit = pci_ich9_uninit; - k->config_write = pci_ich9_write_config; k->vendor_id = PCI_VENDOR_ID_INTEL; k->device_id = PCI_DEVICE_ID_INTEL_82801IR; k->revision = 0x02; k->class_id = PCI_CLASS_STORAGE_SATA; dc->vmsd = &vmstate_ahci; + dc->reset = pci_ich9_reset; } static TypeInfo ich_ahci_info = { diff --git a/hw/intel-hda.c b/hw/intel-hda.c index bb11af286a..8f3b70bd14 100644 --- a/hw/intel-hda.c +++ b/hw/intel-hda.c @@ -1153,17 +1153,6 @@ static int intel_hda_exit(PCIDevice *pci) return 0; } -static void intel_hda_write_config(PCIDevice *pci, uint32_t addr, - uint32_t val, int len) -{ - IntelHDAState *d = DO_UPCAST(IntelHDAState, pci, pci); - - pci_default_write_config(pci, addr, val, len); - if (d->msi) { - msi_write_config(pci, addr, val, len); - } -} - static int intel_hda_post_load(void *opaque, int version) { IntelHDAState* d = opaque; @@ -1252,7 +1241,6 @@ static void intel_hda_class_init(ObjectClass *klass, void *data) k->init = intel_hda_init; k->exit = intel_hda_exit; - k->config_write = intel_hda_write_config; k->vendor_id = PCI_VENDOR_ID_INTEL; k->device_id = 0x2668; k->revision = 1; diff --git a/hw/ioh3420.c b/hw/ioh3420.c index 1632d31c19..0a2601cac4 100644 --- a/hw/ioh3420.c +++ b/hw/ioh3420.c @@ -71,7 +71,6 @@ static void ioh3420_write_config(PCIDevice *d, pci_get_long(d->config + d->exp.aer_cap + PCI_ERR_ROOT_COMMAND); pci_bridge_write_config(d, address, val, len); - msi_write_config(d, address, val, len); ioh3420_aer_vector_update(d); pcie_cap_slot_write_config(d, address, val, len); pcie_aer_write_config(d, address, val, len); @@ -81,7 +80,7 @@ static void ioh3420_write_config(PCIDevice *d, static void ioh3420_reset(DeviceState *qdev) { PCIDevice *d = PCI_DEVICE(qdev); - msi_reset(d); + ioh3420_aer_vector_update(d); pcie_cap_root_reset(d); pcie_cap_deverr_reset(d); diff --git a/hw/ivshmem.c b/hw/ivshmem.c index d48e5f9906..05559b639c 100644 --- a/hw/ivshmem.c +++ b/hw/ivshmem.c @@ -530,7 +530,6 @@ static void ivshmem_reset(DeviceState *d) IVShmemState *s = DO_UPCAST(IVShmemState, dev.qdev, d); s->intrstatus = 0; - msix_reset(&s->dev); ivshmem_use_msix(s); return; } @@ -175,7 +175,7 @@ void msi_uninit(struct PCIDevice *dev) uint16_t flags; uint8_t cap_size; - if (!(dev->cap_present & QEMU_PCI_CAP_MSI)) { + if (!msi_present(dev)) { return; } flags = pci_get_word(dev->config + msi_flags_off(dev)); @@ -191,6 +191,10 @@ void msi_reset(PCIDevice *dev) uint16_t flags; bool msi64bit; + if (!msi_present(dev)) { + return; + } + flags = pci_get_word(dev->config + msi_flags_off(dev)); flags &= ~(PCI_MSI_FLAGS_QSIZE | PCI_MSI_FLAGS_ENABLE); msi64bit = flags & PCI_MSI_FLAGS_64BIT; @@ -260,7 +264,7 @@ void msi_notify(PCIDevice *dev, unsigned int vector) stl_le_phys(address, data); } -/* call this function after updating configs by pci_default_write_config(). */ +/* Normally called by pci_default_write_config(). */ void msi_write_config(PCIDevice *dev, uint32_t addr, uint32_t val, int len) { uint16_t flags = pci_get_word(dev->config + msi_flags_off(dev)); @@ -272,7 +276,8 @@ void msi_write_config(PCIDevice *dev, uint32_t addr, uint32_t val, int len) unsigned int vector; uint32_t pending; - if (!ranges_overlap(addr, len, dev->msi_cap, msi_cap_sizeof(flags))) { + if (!msi_present(dev) || + !ranges_overlap(addr, len, dev->msi_cap, msi_cap_sizeof(flags))) { return; } @@ -187,7 +187,7 @@ void msix_write_config(PCIDevice *dev, uint32_t addr, int vector; bool was_masked; - if (!range_covers_byte(addr, len, enable_pos)) { + if (!msix_present(dev) || !range_covers_byte(addr, len, enable_pos)) { return; } @@ -319,8 +319,9 @@ static void msix_free_irq_entries(PCIDevice *dev) /* Clean up resources for the device. */ int msix_uninit(PCIDevice *dev, MemoryRegion *bar) { - if (!(dev->cap_present & QEMU_PCI_CAP_MSIX)) + if (!msix_present(dev)) { return 0; + } pci_del_capability(dev, PCI_CAP_ID_MSIX, MSIX_CAP_LENGTH); dev->msix_cap = 0; msix_free_irq_entries(dev); @@ -339,7 +340,7 @@ void msix_save(PCIDevice *dev, QEMUFile *f) { unsigned n = dev->msix_entries_nr; - if (!(dev->cap_present & QEMU_PCI_CAP_MSIX)) { + if (!msix_present(dev)) { return; } @@ -353,7 +354,7 @@ void msix_load(PCIDevice *dev, QEMUFile *f) unsigned n = dev->msix_entries_nr; unsigned int vector; - if (!(dev->cap_present & QEMU_PCI_CAP_MSIX)) { + if (!msix_present(dev)) { return; } @@ -407,8 +408,9 @@ void msix_notify(PCIDevice *dev, unsigned vector) void msix_reset(PCIDevice *dev) { - if (!(dev->cap_present & QEMU_PCI_CAP_MSIX)) + if (!msix_present(dev)) { return; + } msix_free_irq_entries(dev); dev->config[dev->msix_cap + MSIX_CONTROL_OFFSET] &= ~dev->wmask[dev->msix_cap + MSIX_CONTROL_OFFSET]; @@ -447,8 +449,9 @@ void msix_vector_unuse(PCIDevice *dev, unsigned vector) void msix_unuse_all_vectors(PCIDevice *dev) { - if (!(dev->cap_present & QEMU_PCI_CAP_MSIX)) + if (!msix_present(dev)) { return; + } msix_free_irq_entries(dev); } @@ -31,6 +31,8 @@ #include "loader.h" #include "range.h" #include "qmp-commands.h" +#include "msi.h" +#include "msix.h" //#define DEBUG_PCI #ifdef DEBUG_PCI @@ -188,6 +190,9 @@ void pci_device_reset(PCIDevice *dev) } } pci_update_mappings(dev); + + msi_reset(dev); + msix_reset(dev); } /* @@ -1037,6 +1042,9 @@ void pci_default_write_config(PCIDevice *d, uint32_t addr, uint32_t val, int l) if (range_covers_byte(addr, l, PCI_COMMAND)) pci_update_irq_disabled(d, was_irq_disabled); + + msi_write_config(d, addr, val, l); + msix_write_config(d, addr, val, l); } /***********************************************************/ diff --git a/hw/pci_bridge.c b/hw/pci_bridge.c index 866f0b6c52..e0832b4a67 100644 --- a/hw/pci_bridge.c +++ b/hw/pci_bridge.c @@ -254,8 +254,9 @@ void pci_bridge_disable_base_limit(PCIDevice *dev) } /* reset bridge specific configuration registers */ -void pci_bridge_reset_reg(PCIDevice *dev) +void pci_bridge_reset(DeviceState *qdev) { + PCIDevice *dev = PCI_DEVICE(qdev); uint8_t *conf = dev->config; conf[PCI_PRIMARY_BUS] = 0; @@ -291,13 +292,6 @@ void pci_bridge_reset_reg(PCIDevice *dev) pci_set_word(conf + PCI_BRIDGE_CONTROL, 0); } -/* default reset function for PCI-to-PCI bridge */ -void pci_bridge_reset(DeviceState *qdev) -{ - PCIDevice *dev = PCI_DEVICE(qdev); - pci_bridge_reset_reg(dev); -} - /* default qdev initialization function for PCI-to-PCI bridge */ int pci_bridge_initfn(PCIDevice *dev) { diff --git a/hw/pci_bridge_dev.c b/hw/pci_bridge_dev.c index eccaa5831e..1cc1d2049c 100644 --- a/hw/pci_bridge_dev.c +++ b/hw/pci_bridge_dev.c @@ -52,7 +52,7 @@ static int pci_bridge_dev_initfn(PCIDevice *dev) { PCIBridge *br = DO_UPCAST(PCIBridge, dev, dev); PCIBridgeDev *bridge_dev = DO_UPCAST(PCIBridgeDev, bridge, br); - int err; + int err, ret; pci_bridge_map_irq(br, NULL, pci_bridge_dev_map_irq_fn); err = pci_bridge_initfn(dev); if (err) { @@ -86,6 +86,8 @@ slotid_error: shpc_cleanup(dev, &bridge_dev->bar); shpc_error: memory_region_destroy(&bridge_dev->bar); + ret = pci_bridge_exitfn(dev); + assert(!ret); bridge_error: return err; } @@ -119,10 +121,8 @@ static void pci_bridge_dev_write_config(PCIDevice *d, static void qdev_pci_bridge_dev_reset(DeviceState *qdev) { PCIDevice *dev = DO_UPCAST(PCIDevice, qdev, qdev); + pci_bridge_reset(qdev); - if (msi_present(dev)) { - msi_reset(dev); - } shpc_reset(dev); } @@ -150,6 +150,7 @@ int qdev_init(DeviceState *dev) rc = dc->init(dev); if (rc < 0) { + object_unparent(OBJECT(dev)); qdev_free(dev); return rc; } diff --git a/hw/rtl8139.c b/hw/rtl8139.c index eb22d04fad..f6f144b525 100644 --- a/hw/rtl8139.c +++ b/hw/rtl8139.c @@ -802,7 +802,7 @@ static int rtl8139_can_receive(VLANClientState *nc) } else { avail = MOD2(s->RxBufferSize + s->RxBufPtr - s->RxBufAddr, s->RxBufferSize); - return (avail == 0 || avail >= 1514); + return (avail == 0 || avail >= 1514 || (s->IntrMask & RxOverflow)); } } @@ -253,6 +253,7 @@ static void shpc_free_devices_in_slot(SHPCDevice *shpc, int slot) ++devfn) { PCIDevice *affected_dev = shpc->sec_bus->devices[devfn]; if (affected_dev) { + object_unparent(OBJECT(affected_dev)); qdev_free(&affected_dev->qdev); } } diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c index d08c1590d2..9342eed070 100644 --- a/hw/virtio-pci.c +++ b/hw/virtio-pci.c @@ -278,7 +278,6 @@ void virtio_pci_reset(DeviceState *d) VirtIOPCIProxy *proxy = container_of(d, VirtIOPCIProxy, pci_dev.qdev); virtio_pci_stop_ioeventfd(proxy); virtio_reset(proxy->vdev); - msix_reset(&proxy->pci_dev); proxy->flags &= ~VIRTIO_PCI_FLAG_BUS_MASTER_BUG; } @@ -521,8 +520,6 @@ static void virtio_write_config(PCIDevice *pci_dev, uint32_t address, virtio_set_status(proxy->vdev, proxy->vdev->status & ~VIRTIO_CONFIG_S_DRIVER_OK); } - - msix_write_config(pci_dev, address, val, len); } static unsigned virtio_pci_get_features(void *opaque) diff --git a/hw/xio3130_downstream.c b/hw/xio3130_downstream.c index 319624f212..56d1b353d0 100644 --- a/hw/xio3130_downstream.c +++ b/hw/xio3130_downstream.c @@ -41,14 +41,13 @@ static void xio3130_downstream_write_config(PCIDevice *d, uint32_t address, pci_bridge_write_config(d, address, val, len); pcie_cap_flr_write_config(d, address, val, len); pcie_cap_slot_write_config(d, address, val, len); - msi_write_config(d, address, val, len); pcie_aer_write_config(d, address, val, len); } static void xio3130_downstream_reset(DeviceState *qdev) { PCIDevice *d = PCI_DEVICE(qdev); - msi_reset(d); + pcie_cap_deverr_reset(d); pcie_cap_slot_reset(d); pcie_cap_ari_reset(d); diff --git a/hw/xio3130_upstream.c b/hw/xio3130_upstream.c index 34a99bba08..79725813a2 100644 --- a/hw/xio3130_upstream.c +++ b/hw/xio3130_upstream.c @@ -40,14 +40,13 @@ static void xio3130_upstream_write_config(PCIDevice *d, uint32_t address, { pci_bridge_write_config(d, address, val, len); pcie_cap_flr_write_config(d, address, val, len); - msi_write_config(d, address, val, len); pcie_aer_write_config(d, address, val, len); } static void xio3130_upstream_reset(DeviceState *qdev) { PCIDevice *d = PCI_DEVICE(qdev); - msi_reset(d); + pci_bridge_reset(qdev); pcie_cap_deverr_reset(d); } |