diff options
author | Anthony Liguori <aliguori@us.ibm.com> | 2011-01-20 09:05:37 -0600 |
---|---|---|
committer | Anthony Liguori <aliguori@us.ibm.com> | 2011-01-20 09:05:37 -0600 |
commit | 5dbbda340533cd7d217dcf3ab904fb353598cbde (patch) | |
tree | 1e0bc27430f12e9f27bdd466a21072802f7cbbb5 /hw | |
parent | d788b57051ee91aa39de67cff8d8e15953bc100c (diff) | |
parent | e10990c3f0c39e92ab5f74004b89a24fcc36fa14 (diff) |
Merge remote branch 'mst/for_anthony' into staging
Diffstat (limited to 'hw')
-rw-r--r-- | hw/acpi_piix4.c | 37 | ||||
-rw-r--r-- | hw/msi.c | 5 | ||||
-rw-r--r-- | hw/msix.c | 5 | ||||
-rw-r--r-- | hw/pci.c | 27 | ||||
-rw-r--r-- | hw/pci.h | 2 | ||||
-rw-r--r-- | hw/virtio-serial-bus.c | 10 |
6 files changed, 71 insertions, 15 deletions
diff --git a/hw/acpi_piix4.c b/hw/acpi_piix4.c index 273097d480..5bbc2b5a26 100644 --- a/hw/acpi_piix4.c +++ b/hw/acpi_piix4.c @@ -37,6 +37,7 @@ #define GPE_BASE 0xafe0 #define PCI_BASE 0xae00 #define PCI_EJ_BASE 0xae08 +#define PCI_RMV_BASE 0xae0c #define PIIX4_PCI_HOTPLUG_STATUS 2 @@ -73,6 +74,7 @@ typedef struct PIIX4PMState { /* for pci hotplug */ struct gpe_regs gpe; struct pci_status pci0_status; + uint32_t pci0_hotplug_enable; } PIIX4PMState; static void piix4_acpi_system_hot_add_init(PCIBus *bus, PIIX4PMState *s); @@ -322,6 +324,25 @@ static const VMStateDescription vmstate_acpi = { } }; +static void piix4_update_hotplug(PIIX4PMState *s) +{ + PCIDevice *dev = &s->dev; + BusState *bus = qdev_get_parent_bus(&dev->qdev); + DeviceState *qdev, *next; + + s->pci0_hotplug_enable = ~0; + + QLIST_FOREACH_SAFE(qdev, &bus->children, sibling, next) { + PCIDeviceInfo *info = container_of(qdev->info, PCIDeviceInfo, qdev); + PCIDevice *pdev = DO_UPCAST(PCIDevice, qdev, qdev); + int slot = PCI_SLOT(pdev->devfn); + + if (info->no_hotplug) { + s->pci0_hotplug_enable &= ~(1 << slot); + } + } +} + static void piix4_reset(void *opaque) { PIIX4PMState *s = opaque; @@ -336,6 +357,7 @@ static void piix4_reset(void *opaque) /* Mark SMM as already inited (until KVM supports SMM). */ pci_conf[0x5B] = 0x02; } + piix4_update_hotplug(s); } static void piix4_powerdown(void *opaque, int irq, int power_failing) @@ -576,6 +598,18 @@ static void pciej_write(void *opaque, uint32_t addr, uint32_t val) PIIX4_DPRINTF("pciej write %x <== %d\n", addr, val); } +static uint32_t pcirmv_read(void *opaque, uint32_t addr) +{ + PIIX4PMState *s = opaque; + + return s->pci0_hotplug_enable; +} + +static void pcirmv_write(void *opaque, uint32_t addr, uint32_t val) +{ + return; +} + static int piix4_device_hotplug(DeviceState *qdev, PCIDevice *dev, PCIHotplugState state); @@ -592,6 +626,9 @@ static void piix4_acpi_system_hot_add_init(PCIBus *bus, PIIX4PMState *s) register_ioport_write(PCI_EJ_BASE, 4, 4, pciej_write, bus); register_ioport_read(PCI_EJ_BASE, 4, 4, pciej_read, bus); + register_ioport_write(PCI_RMV_BASE, 4, 4, pcirmv_write, s); + register_ioport_read(PCI_RMV_BASE, 4, 4, pcirmv_read, s); + pci_bus_hotplug(bus, piix4_device_hotplug, &s->dev.qdev); } @@ -255,7 +255,6 @@ void msi_write_config(PCIDevice *dev, uint32_t addr, uint32_t val, int len) uint8_t log_max_vecs; unsigned int vector; uint32_t pending; - int i; if (!ranges_overlap(addr, len, dev->msi_cap, msi_cap_sizeof(flags))) { return; @@ -296,9 +295,7 @@ void msi_write_config(PCIDevice *dev, uint32_t addr, uint32_t val, int len) * from using its INTx# pin (if implemented) to request * service (MSI, MSI-X, and INTx# are mutually exclusive). */ - for (i = 0; i < PCI_NUM_PINS; ++i) { - qemu_set_irq(dev->irq[i], 0); - } + pci_device_deassert_intx(dev); /* * nr_vectors might be set bigger than capable. So clamp it. @@ -159,7 +159,6 @@ void msix_write_config(PCIDevice *dev, uint32_t addr, { unsigned enable_pos = dev->msix_cap + MSIX_CONTROL_OFFSET; int vector; - int i; if (!range_covers_byte(addr, len, enable_pos)) { return; @@ -169,9 +168,7 @@ void msix_write_config(PCIDevice *dev, uint32_t addr, return; } - for (i = 0; i < PCI_NUM_PINS; ++i) { - qemu_set_irq(dev->irq[i], 0); - } + pci_device_deassert_intx(dev); if (msix_function_masked(dev)) { return; @@ -137,6 +137,14 @@ static void pci_update_irq_status(PCIDevice *dev) } } +void pci_device_deassert_intx(PCIDevice *dev) +{ + int i; + for (i = 0; i < PCI_NUM_PINS; ++i) { + qemu_set_irq(dev->irq[i], 0); + } +} + /* * This function is called on #RST and FLR. * FLR if PCI_EXP_DEVCTL_BCR_FLR is set @@ -152,6 +160,7 @@ void pci_device_reset(PCIDevice *dev) dev->irq_state = 0; pci_update_irq_status(dev); + pci_device_deassert_intx(dev); /* Clear all writeable bits */ pci_word_test_and_clear_mask(dev->config + PCI_COMMAND, pci_get_word(dev->wmask + PCI_COMMAND) | @@ -2032,10 +2041,13 @@ static char *pcibus_get_dev_path(DeviceState *dev) * domain:Bus:Slot.Func for systems without nested PCI bridges. * Slot.Function list specifies the slot and function numbers for all * devices on the path from root to the specific device. */ - int domain_len = strlen("DDDD:00"); - int slot_len = strlen(":SS.F"); + char domain[] = "DDDD:00"; + char slot[] = ":SS.F"; + int domain_len = sizeof domain - 1 /* For '\0' */; + int slot_len = sizeof slot - 1 /* For '\0' */; int path_len; char *path, *p; + int s; /* Calculate # of slots on path between device and root. */; slot_depth = 0; @@ -2046,18 +2058,23 @@ static char *pcibus_get_dev_path(DeviceState *dev) path_len = domain_len + slot_len * slot_depth; /* Allocate memory, fill in the terminating null byte. */ - path = malloc(path_len + 1 /* For '\0' */); + path = qemu_malloc(path_len + 1 /* For '\0' */); path[path_len] = '\0'; /* First field is the domain. */ - snprintf(path, domain_len, "%04x:00", pci_find_domain(d->bus)); + s = snprintf(domain, sizeof domain, "%04x:00", pci_find_domain(d->bus)); + assert(s == domain_len); + memcpy(path, domain, domain_len); /* Fill in slot numbers. We walk up from device to root, so need to print * them in the reverse order, last to first. */ p = path + path_len; for (t = d; t; t = t->bus->parent_dev) { p -= slot_len; - snprintf(p, slot_len, ":%02x.%x", PCI_SLOT(t->devfn), PCI_FUNC(d->devfn)); + s = snprintf(slot, sizeof slot, ":%02x.%x", + PCI_SLOT(t->devfn), PCI_FUNC(d->devfn)); + assert(s == slot_len); + memcpy(p, slot, slot_len); } return path; @@ -264,6 +264,8 @@ void do_pci_info_print(Monitor *mon, const QObject *data); void do_pci_info(Monitor *mon, QObject **ret_data); void pci_bridge_update_mappings(PCIBus *b); +void pci_device_deassert_intx(PCIDevice *dev); + static inline void pci_set_byte(uint8_t *config, uint8_t val) { diff --git a/hw/virtio-serial-bus.c b/hw/virtio-serial-bus.c index 74ba5ec3d3..b728040f3a 100644 --- a/hw/virtio-serial-bus.c +++ b/hw/virtio-serial-bus.c @@ -769,10 +769,16 @@ VirtIODevice *virtio_serial_init(DeviceState *dev, uint32_t max_nr_ports) /* Add a queue for guest to host transfers for port 0 (backward compat) */ vser->ovqs[0] = virtio_add_queue(vdev, 128, handle_output); + /* TODO: host to guest notifications can get dropped + * if the queue fills up. Implement queueing in host, + * this might also make it possible to reduce the control + * queue size: as guest preposts buffers there, + * this will save 4Kbyte of guest memory per entry. */ + /* control queue: host to guest */ - vser->c_ivq = virtio_add_queue(vdev, 16, control_in); + vser->c_ivq = virtio_add_queue(vdev, 32, control_in); /* control queue: guest to host */ - vser->c_ovq = virtio_add_queue(vdev, 16, control_out); + vser->c_ovq = virtio_add_queue(vdev, 32, control_out); for (i = 1; i < vser->bus->max_nr_ports; i++) { /* Add a per-port queue for host to guest transfers */ |