[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-devel] [PATCH 03/13] pci: Introduce cached device INTx routing
From: |
Michael S. Tsirkin |
Subject: |
Re: [Qemu-devel] [PATCH 03/13] pci: Introduce cached device INTx routing |
Date: |
Sun, 10 Jun 2012 14:28:01 +0300 |
On Mon, Jun 04, 2012 at 10:52:11AM +0200, Jan Kiszka wrote:
> Based on the original version by Michael Tsirkin: Instead of traversing
> the PCI bus hierarchy from a device to the host bridge, cache this path
> in PCIDevice and use it directly on interrupt delivery. This will
> specifically pay off with more complex topologies than the current
> single host bus.
>
> Signed-off-by: Jan Kiszka <address@hidden>
OK, I applied this. I still think we should go the extra
mile and cache the final IRQ not just the root intx.
But that can be a patch on top.
> ---
> hw/pci.c | 53 ++++++++++++++++++++++++++++++++++++++++++++---------
> hw/pci.h | 4 ++++
> 2 files changed, 48 insertions(+), 9 deletions(-)
>
> diff --git a/hw/pci.c b/hw/pci.c
> index 33452ab..771fb39 100644
> --- a/hw/pci.c
> +++ b/hw/pci.c
> @@ -68,6 +68,8 @@ static void pci_update_mappings(PCIDevice *d);
> static void pci_set_irq(void *opaque, int irq_num, int level);
> static int pci_add_option_rom(PCIDevice *pdev, bool is_default_rom);
> static void pci_del_option_rom(PCIDevice *pdev);
> +static void pci_for_each_device_under_bus(PCIBus *bus,
> + void (*fn)(PCIBus *b, PCIDevice
> *d));
>
> static uint16_t pci_default_sub_vendor_id = PCI_SUBVENDOR_ID_REDHAT_QUMRANET;
> static uint16_t pci_default_sub_device_id = PCI_SUBDEVICE_ID_QEMU;
> @@ -112,18 +114,49 @@ static inline void pci_set_irq_state(PCIDevice *d, int
> irq_num, int level)
> d->irq_state |= level << irq_num;
> }
>
> -static void pci_change_irq_level(PCIDevice *pci_dev, int irq_num, int change)
> +static void pci_set_device_intx_routing(PCIBus *bus, PCIDevice *dev)
> {
> - PCIBus *bus;
> + int pin, output_pin;
> + PCIDevice *pci_dev;
> +
> + /* We might be too early, i.e. before pci_bus_irqs was called.
> + * We will be called again when this happened. */
> + if (!bus->map_irq) {
> + return;
> + }
> +
> + for (pin = 0; pin < PCI_NUM_PINS; pin++) {
> + pci_dev = dev;
> + output_pin = pin;
> + do {
> + bus = pci_dev->bus;
> + output_pin = bus->map_irq(pci_dev, output_pin);
> + pci_dev = bus->parent_dev;
> + } while (pci_dev);
> +
> + dev->host_intx_pin[pin] = output_pin;
> + dev->host_bus = bus;
> + }
> +}
> +
> +static void pci_set_bus_intx_routing(PCIBus *bus)
> +{
> + PCIBus *sec;
> +
> + pci_for_each_device_under_bus(bus, pci_set_device_intx_routing);
>
> - do {
> - bus = pci_dev->bus;
> - irq_num = bus->map_irq(pci_dev, irq_num);
> - pci_dev = bus->parent_dev;
> - } while (pci_dev);
> + QLIST_FOREACH(sec, &bus->child, sibling) {
> + pci_set_bus_intx_routing(sec);
> + }
> +}
> +
> +static void pci_change_irq_level(PCIDevice *dev, int pin, int change)
> +{
> + PCIBus *bus = dev->host_bus;
> + int output_pin = dev->host_intx_pin[pin];
>
> - bus->irq_count[irq_num] += change;
> - bus->set_irq(bus->irq_opaque, irq_num, bus->irq_count[irq_num] != 0);
> + bus->irq_count[output_pin] += change;
> + bus->set_irq(bus->irq_opaque, output_pin, bus->irq_count[output_pin] !=
> 0);
> }
>
> int pci_bus_get_irq_level(PCIBus *bus, int irq_num)
> @@ -293,6 +326,7 @@ void pci_bus_irqs(PCIBus *bus, pci_set_irq_fn set_irq,
> pci_map_irq_fn map_irq,
> bus->irq_opaque = irq_opaque;
> bus->nirq = nirq;
> bus->irq_count = g_malloc0(nirq * sizeof(bus->irq_count[0]));
> + pci_set_bus_intx_routing(bus);
> }
>
> void pci_bus_hotplug(PCIBus *bus, pci_hotplug_fn hotplug, DeviceState *qdev)
> @@ -798,6 +832,7 @@ static PCIDevice *do_pci_register_device(PCIDevice
> *pci_dev, PCIBus *bus,
> bus->devices[devfn] = pci_dev;
> pci_dev->irq = qemu_allocate_irqs(pci_set_irq, pci_dev, PCI_NUM_PINS);
> pci_dev->version_id = 2; /* Current pci device vmstate version */
> + pci_set_device_intx_routing(bus, pci_dev);
> return pci_dev;
> }
>
> diff --git a/hw/pci.h b/hw/pci.h
> index 7eaf90b..c4fd863 100644
> --- a/hw/pci.h
> +++ b/hw/pci.h
> @@ -211,6 +211,10 @@ struct PCIDevice {
> /* Current IRQ levels. Used internally by the generic PCI code. */
> uint8_t irq_state;
>
> + /* Used internally by PCI code to cache the interrupt routing */
> + PCIBus *host_bus;
> + int host_intx_pin[PCI_NUM_PINS];
> +
A better name would be root_XXXX: host is an overloaded term.
I applied such a patch.
> /* Capability bits */
> uint32_t cap_present;
>
> --
> 1.7.3.4
- [Qemu-devel] [PATCH 00/13] pci: Cleanups & preparations for KVM device assignment, Jan Kiszka, 2012/06/04
- [Qemu-devel] [PATCH 02/13] pci: Fold pci_bus_new_inplace into pci_bus_new, Jan Kiszka, 2012/06/04
- [Qemu-devel] [PATCH 10/13] pci: Fix coding style of pci_parse_devaddr, Jan Kiszka, 2012/06/04
- [Qemu-devel] [PATCH 03/13] pci: Introduce cached device INTx routing, Jan Kiszka, 2012/06/04
- Re: [Qemu-devel] [PATCH 03/13] pci: Introduce cached device INTx routing,
Michael S. Tsirkin <=
- [Qemu-devel] [PATCH 11/13] Move pci_parse_devaddr to qdev-properties, Jan Kiszka, 2012/06/04
- Re: [Qemu-devel] [PATCH 11/13] Move pci_parse_devaddr to qdev-properties, Andreas Färber, 2012/06/07
- Re: [Qemu-devel] [PATCH 11/13] Move pci_parse_devaddr to qdev-properties, Jan Kiszka, 2012/06/07
- Re: [Qemu-devel] [PATCH 11/13] Move pci_parse_devaddr to qdev-properties, Andreas Färber, 2012/06/07
- Re: [Qemu-devel] [PATCH 11/13] Move pci_parse_devaddr to qdev-properties, Jan Kiszka, 2012/06/08
- Re: [Qemu-devel] [PATCH 11/13] Move pci_parse_devaddr to qdev-properties, Andreas Färber, 2012/06/08
- Re: [Qemu-devel] [PATCH 11/13] Move pci_parse_devaddr to qdev-properties, Jan Kiszka, 2012/06/08
- Re: [Qemu-devel] [PATCH 11/13] Move pci_parse_devaddr to qdev-properties, Andreas Färber, 2012/06/08
- Re: [Qemu-devel] [PATCH 11/13] Move pci_parse_devaddr to qdev-properties, Jan Kiszka, 2012/06/08
- Re: [Qemu-devel] [PATCH 11/13] Move pci_parse_devaddr to qdev-properties, Michael S. Tsirkin, 2012/06/08