aboutsummaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
authorAnthony Liguori <aliguori@us.ibm.com>2012-06-18 10:18:44 -0500
committerAnthony Liguori <aliguori@us.ibm.com>2012-06-18 10:18:44 -0500
commitdf6606f4556a752d30a4eab26c626b6c34717ea8 (patch)
tree095df894fd2f1e40f6a8a5a6393e10a953d8054d /hw
parent49023ff78cf1efeb861b475c40dd04262efe61d3 (diff)
parent80aa796bf38b7ef21daa42673b4711510c450d8a (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.c25
-rw-r--r--hw/ide/ahci.h2
-rw-r--r--hw/ide/ich.c19
-rw-r--r--hw/intel-hda.c12
-rw-r--r--hw/ioh3420.c3
-rw-r--r--hw/ivshmem.c1
-rw-r--r--hw/msi.c11
-rw-r--r--hw/msix.c15
-rw-r--r--hw/pci.c8
-rw-r--r--hw/pci_bridge.c10
-rw-r--r--hw/pci_bridge_dev.c8
-rw-r--r--hw/qdev.c1
-rw-r--r--hw/rtl8139.c2
-rw-r--r--hw/shpc.c1
-rw-r--r--hw/virtio-pci.c3
-rw-r--r--hw/xio3130_downstream.c3
-rw-r--r--hw/xio3130_upstream.c3
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;
}
diff --git a/hw/msi.c b/hw/msi.c
index 5d6ceb6df0..52332041e7 100644
--- a/hw/msi.c
+++ b/hw/msi.c
@@ -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;
}
diff --git a/hw/msix.c b/hw/msix.c
index 59c7a8388f..ded3c55b92 100644
--- a/hw/msix.c
+++ b/hw/msix.c
@@ -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);
}
diff --git a/hw/pci.c b/hw/pci.c
index 127b7aca73..9daa0bfb20 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -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);
}
diff --git a/hw/qdev.c b/hw/qdev.c
index 6a8f6bda2b..af419b9c13 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -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));
}
}
diff --git a/hw/shpc.c b/hw/shpc.c
index a5baf246f1..6b9884d544 100644
--- a/hw/shpc.c
+++ b/hw/shpc.c
@@ -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);
}