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
This commit is contained in:
Anthony Liguori 2012-06-18 10:18:44 -05:00
commit df6606f455
17 changed files with 61 additions and 66 deletions

View File

@ -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 = {

View File

@ -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 */

View File

@ -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 = {

View File

@ -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;

View File

@ -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);

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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);
}
/***********************************************************/

View File

@ -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)
{

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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));
}
}

View File

@ -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);
}
}

View File

@ -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)

View File

@ -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);

View File

@ -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);
}