Message ID | 20130123020429.28329.65700.stgit@bling.home |
---|---|
State | New |
Headers | show |
On Tue, Jan 22, 2013 at 07:11:37PM -0700, Alex Williamson wrote: > Fills out support for the pci assignment API. Added: > > PCIINTxRoute ich9_route_intx_pin_to_irq(void *opaque, int pirq_pin) > > Add calls to pci_bus_fire_intx_routing_notifier() when routing changes > are made. > > From: Jason Baron <jbaron@redhat.com> > Signed-off-by: Alex Williamson <alex.williamson@redhat.com> Anthony any objection if I keep merging these things? You wanted to be in control when the bulk of the q35 work was being merged but I'm guessing it's ok now? > --- > > Jason posted this back in October, there were no comments. Updated > and tested for latest tree. Currently attempting to use -device > pci-assign with q35 results in: > > qemu-system-x86_64: -device pci-assign,host=b:00.0,addr=6: PCI: Bug - unimplemented PCI INTx routing (q35-pcihost) > > This allows it to work. Note that there's a seabios bug for option > ROMs making use of interrupts, hopefully we can also pull that fix > in for 1.4, but guests not relying on bios programming of the PCI > interrupt line value should work fine. > > hw/ich9.h | 1 + > hw/lpc_ich9.c | 33 +++++++++++++++++++++++++++++++++ > hw/pc_q35.c | 1 + > 3 files changed, 35 insertions(+) > > diff --git a/hw/ich9.h b/hw/ich9.h > index b8d8e6d..d4509bb 100644 > --- a/hw/ich9.h > +++ b/hw/ich9.h > @@ -18,6 +18,7 @@ > > void ich9_lpc_set_irq(void *opaque, int irq_num, int level); > int ich9_lpc_map_irq(PCIDevice *pci_dev, int intx); > +PCIINTxRoute ich9_route_intx_pin_to_irq(void *opaque, int pirq_pin); > void ich9_lpc_pm_init(PCIDevice *pci_lpc, qemu_irq cmos_s3); > PCIBus *ich9_d2pbr_init(PCIBus *bus, int devfn, int sec_bus); > i2c_bus *ich9_smb_init(PCIBus *bus, int devfn, uint32_t smb_io_base); > diff --git a/hw/lpc_ich9.c b/hw/lpc_ich9.c > index 16843d7..e25689b 100644 > --- a/hw/lpc_ich9.c > +++ b/hw/lpc_ich9.c > @@ -158,6 +158,7 @@ static void ich9_cc_write(void *opaque, hwaddr addr, > > ich9_cc_addr_len(&addr, &len); > memcpy(lpc->chip_config + addr, &val, len); > + pci_bus_fire_intx_routing_notifier(lpc->d.bus); > ich9_cc_update(lpc); > } > > @@ -286,6 +287,32 @@ int ich9_lpc_map_irq(PCIDevice *pci_dev, int intx) > return lpc->irr[PCI_SLOT(pci_dev->devfn)][intx]; > } > > +PCIINTxRoute ich9_route_intx_pin_to_irq(void *opaque, int pirq_pin) > +{ > + ICH9LPCState *lpc = opaque; > + PCIINTxRoute route; > + int pic_irq; > + int pic_dis; > + > + assert(0 <= pirq_pin); > + assert(pirq_pin < ICH9_LPC_NB_PIRQS); > + > + route.mode = PCI_INTX_ENABLED; > + ich9_lpc_pic_irq(lpc, pirq_pin, &pic_irq, &pic_dis); > + if (!pic_dis) { > + if (pic_irq < ICH9_LPC_PIC_NUM_PINS) { > + route.irq = pic_irq; > + } else { > + route.mode = PCI_INTX_DISABLED; > + route.irq = -1; > + } > + } else { > + route.irq = ich9_pirq_to_gsi(pirq_pin); > + } > + > + return route; > +} > + > static int ich9_lpc_sci_irq(ICH9LPCState *lpc) > { > switch (lpc->d.config[ICH9_LPC_ACPI_CTRL] & > @@ -405,6 +432,12 @@ static void ich9_lpc_config_write(PCIDevice *d, > if (ranges_overlap(addr, len, ICH9_LPC_RCBA, 4)) { > ich9_lpc_rcba_update(lpc, rbca_old); > } > + if (ranges_overlap(addr, len, ICH9_LPC_PIRQA_ROUT, 4)) { > + pci_bus_fire_intx_routing_notifier(lpc->d.bus); > + } > + if (ranges_overlap(addr, len, ICH9_LPC_PIRQE_ROUT, 4)) { > + pci_bus_fire_intx_routing_notifier(lpc->d.bus); > + } > } > > static void ich9_lpc_reset(DeviceState *qdev) > diff --git a/hw/pc_q35.c b/hw/pc_q35.c > index d82353e..6f5ff8d 100644 > --- a/hw/pc_q35.c > +++ b/hw/pc_q35.c > @@ -147,6 +147,7 @@ static void pc_q35_init(QEMUMachineInitArgs *args) > ich9_lpc->ioapic = gsi_state->ioapic_irq; > pci_bus_irqs(host_bus, ich9_lpc_set_irq, ich9_lpc_map_irq, ich9_lpc, > ICH9_LPC_NB_PIRQS); > + pci_bus_set_route_irq_fn(host_bus, ich9_route_intx_pin_to_irq); > isa_bus = ich9_lpc->isa_bus; > > /*end early*/
On Tue, Jan 22, 2013 at 07:11:37PM -0700, Alex Williamson wrote: > Fills out support for the pci assignment API. Added: > > PCIINTxRoute ich9_route_intx_pin_to_irq(void *opaque, int pirq_pin) > > Add calls to pci_bus_fire_intx_routing_notifier() when routing changes > are made. > > From: Jason Baron <jbaron@redhat.com> > Signed-off-by: Alex Williamson <alex.williamson@redhat.com> Applied, thanks for repost (note for the future: it's preferable put the From: at top of the commit log, this way git am knows to pick it up). > --- > > Jason posted this back in October, there were no comments. Updated > and tested for latest tree. Currently attempting to use -device > pci-assign with q35 results in: > > qemu-system-x86_64: -device pci-assign,host=b:00.0,addr=6: PCI: Bug - unimplemented PCI INTx routing (q35-pcihost) > > This allows it to work. Note that there's a seabios bug for option > ROMs making use of interrupts, hopefully we can also pull that fix > in for 1.4, but guests not relying on bios programming of the PCI > interrupt line value should work fine. > > hw/ich9.h | 1 + > hw/lpc_ich9.c | 33 +++++++++++++++++++++++++++++++++ > hw/pc_q35.c | 1 + > 3 files changed, 35 insertions(+) > > diff --git a/hw/ich9.h b/hw/ich9.h > index b8d8e6d..d4509bb 100644 > --- a/hw/ich9.h > +++ b/hw/ich9.h > @@ -18,6 +18,7 @@ > > void ich9_lpc_set_irq(void *opaque, int irq_num, int level); > int ich9_lpc_map_irq(PCIDevice *pci_dev, int intx); > +PCIINTxRoute ich9_route_intx_pin_to_irq(void *opaque, int pirq_pin); > void ich9_lpc_pm_init(PCIDevice *pci_lpc, qemu_irq cmos_s3); > PCIBus *ich9_d2pbr_init(PCIBus *bus, int devfn, int sec_bus); > i2c_bus *ich9_smb_init(PCIBus *bus, int devfn, uint32_t smb_io_base); > diff --git a/hw/lpc_ich9.c b/hw/lpc_ich9.c > index 16843d7..e25689b 100644 > --- a/hw/lpc_ich9.c > +++ b/hw/lpc_ich9.c > @@ -158,6 +158,7 @@ static void ich9_cc_write(void *opaque, hwaddr addr, > > ich9_cc_addr_len(&addr, &len); > memcpy(lpc->chip_config + addr, &val, len); > + pci_bus_fire_intx_routing_notifier(lpc->d.bus); > ich9_cc_update(lpc); > } > > @@ -286,6 +287,32 @@ int ich9_lpc_map_irq(PCIDevice *pci_dev, int intx) > return lpc->irr[PCI_SLOT(pci_dev->devfn)][intx]; > } > > +PCIINTxRoute ich9_route_intx_pin_to_irq(void *opaque, int pirq_pin) > +{ > + ICH9LPCState *lpc = opaque; > + PCIINTxRoute route; > + int pic_irq; > + int pic_dis; > + > + assert(0 <= pirq_pin); > + assert(pirq_pin < ICH9_LPC_NB_PIRQS); > + > + route.mode = PCI_INTX_ENABLED; > + ich9_lpc_pic_irq(lpc, pirq_pin, &pic_irq, &pic_dis); > + if (!pic_dis) { > + if (pic_irq < ICH9_LPC_PIC_NUM_PINS) { > + route.irq = pic_irq; > + } else { > + route.mode = PCI_INTX_DISABLED; > + route.irq = -1; > + } > + } else { > + route.irq = ich9_pirq_to_gsi(pirq_pin); > + } > + > + return route; > +} > + > static int ich9_lpc_sci_irq(ICH9LPCState *lpc) > { > switch (lpc->d.config[ICH9_LPC_ACPI_CTRL] & > @@ -405,6 +432,12 @@ static void ich9_lpc_config_write(PCIDevice *d, > if (ranges_overlap(addr, len, ICH9_LPC_RCBA, 4)) { > ich9_lpc_rcba_update(lpc, rbca_old); > } > + if (ranges_overlap(addr, len, ICH9_LPC_PIRQA_ROUT, 4)) { > + pci_bus_fire_intx_routing_notifier(lpc->d.bus); > + } > + if (ranges_overlap(addr, len, ICH9_LPC_PIRQE_ROUT, 4)) { > + pci_bus_fire_intx_routing_notifier(lpc->d.bus); > + } > } > > static void ich9_lpc_reset(DeviceState *qdev) > diff --git a/hw/pc_q35.c b/hw/pc_q35.c > index d82353e..6f5ff8d 100644 > --- a/hw/pc_q35.c > +++ b/hw/pc_q35.c > @@ -147,6 +147,7 @@ static void pc_q35_init(QEMUMachineInitArgs *args) > ich9_lpc->ioapic = gsi_state->ioapic_irq; > pci_bus_irqs(host_bus, ich9_lpc_set_irq, ich9_lpc_map_irq, ich9_lpc, > ICH9_LPC_NB_PIRQS); > + pci_bus_set_route_irq_fn(host_bus, ich9_route_intx_pin_to_irq); > isa_bus = ich9_lpc->isa_bus; > > /*end early*/
diff --git a/hw/ich9.h b/hw/ich9.h index b8d8e6d..d4509bb 100644 --- a/hw/ich9.h +++ b/hw/ich9.h @@ -18,6 +18,7 @@ void ich9_lpc_set_irq(void *opaque, int irq_num, int level); int ich9_lpc_map_irq(PCIDevice *pci_dev, int intx); +PCIINTxRoute ich9_route_intx_pin_to_irq(void *opaque, int pirq_pin); void ich9_lpc_pm_init(PCIDevice *pci_lpc, qemu_irq cmos_s3); PCIBus *ich9_d2pbr_init(PCIBus *bus, int devfn, int sec_bus); i2c_bus *ich9_smb_init(PCIBus *bus, int devfn, uint32_t smb_io_base); diff --git a/hw/lpc_ich9.c b/hw/lpc_ich9.c index 16843d7..e25689b 100644 --- a/hw/lpc_ich9.c +++ b/hw/lpc_ich9.c @@ -158,6 +158,7 @@ static void ich9_cc_write(void *opaque, hwaddr addr, ich9_cc_addr_len(&addr, &len); memcpy(lpc->chip_config + addr, &val, len); + pci_bus_fire_intx_routing_notifier(lpc->d.bus); ich9_cc_update(lpc); } @@ -286,6 +287,32 @@ int ich9_lpc_map_irq(PCIDevice *pci_dev, int intx) return lpc->irr[PCI_SLOT(pci_dev->devfn)][intx]; } +PCIINTxRoute ich9_route_intx_pin_to_irq(void *opaque, int pirq_pin) +{ + ICH9LPCState *lpc = opaque; + PCIINTxRoute route; + int pic_irq; + int pic_dis; + + assert(0 <= pirq_pin); + assert(pirq_pin < ICH9_LPC_NB_PIRQS); + + route.mode = PCI_INTX_ENABLED; + ich9_lpc_pic_irq(lpc, pirq_pin, &pic_irq, &pic_dis); + if (!pic_dis) { + if (pic_irq < ICH9_LPC_PIC_NUM_PINS) { + route.irq = pic_irq; + } else { + route.mode = PCI_INTX_DISABLED; + route.irq = -1; + } + } else { + route.irq = ich9_pirq_to_gsi(pirq_pin); + } + + return route; +} + static int ich9_lpc_sci_irq(ICH9LPCState *lpc) { switch (lpc->d.config[ICH9_LPC_ACPI_CTRL] & @@ -405,6 +432,12 @@ static void ich9_lpc_config_write(PCIDevice *d, if (ranges_overlap(addr, len, ICH9_LPC_RCBA, 4)) { ich9_lpc_rcba_update(lpc, rbca_old); } + if (ranges_overlap(addr, len, ICH9_LPC_PIRQA_ROUT, 4)) { + pci_bus_fire_intx_routing_notifier(lpc->d.bus); + } + if (ranges_overlap(addr, len, ICH9_LPC_PIRQE_ROUT, 4)) { + pci_bus_fire_intx_routing_notifier(lpc->d.bus); + } } static void ich9_lpc_reset(DeviceState *qdev) diff --git a/hw/pc_q35.c b/hw/pc_q35.c index d82353e..6f5ff8d 100644 --- a/hw/pc_q35.c +++ b/hw/pc_q35.c @@ -147,6 +147,7 @@ static void pc_q35_init(QEMUMachineInitArgs *args) ich9_lpc->ioapic = gsi_state->ioapic_irq; pci_bus_irqs(host_bus, ich9_lpc_set_irq, ich9_lpc_map_irq, ich9_lpc, ICH9_LPC_NB_PIRQS); + pci_bus_set_route_irq_fn(host_bus, ich9_route_intx_pin_to_irq); isa_bus = ich9_lpc->isa_bus; /*end early*/