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:
commit
df6606f455
@ -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 = {
|
||||
|
@ -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 */
|
||||
|
19
hw/ide/ich.c
19
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 = {
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
11
hw/msi.c
11
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;
|
||||
}
|
||||
|
||||
|
15
hw/msix.c
15
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);
|
||||
}
|
||||
|
||||
|
8
hw/pci.c
8
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);
|
||||
}
|
||||
|
||||
/***********************************************************/
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user