Message ID | 4FA3F72E.7080103@redhat.com |
---|---|
State | New |
Headers | show |
On Fri, May 04, 2012 at 05:35:10PM +0200, Gerd Hoffmann wrote: > On 05/04/12 15:15, Kevin O'Connor wrote: > > On Fri, May 04, 2012 at 10:21:23AM +0200, Gerd Hoffmann wrote: > >> seabios used to initialize root bus devices only, with this patch > >> devices behind pci bridges are initialized too. This allows to boot > >> from virtio devices behind pci bridges. [...] > > I think this will then assign an incorrect PCI_INTERRUPT_LINE value to > > non root bus devices. > > Attached patch should fix it if I read the specs correctly. > Untested though, review appreciated. It looks good to me from a read of the spec as well. I'm not sure how to test it. -Kevin
On Fri, May 04, 2012 at 05:35:10PM +0200, Gerd Hoffmann wrote: > On 05/04/12 15:15, Kevin O'Connor wrote: > > On Fri, May 04, 2012 at 10:21:23AM +0200, Gerd Hoffmann wrote: > >> seabios used to initialize root bus devices only, with this patch > >> devices behind pci bridges are initialized too. This allows to boot > >> from virtio devices behind pci bridges. > >> > >> Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> > >> --- > >> src/pciinit.c | 3 --- > >> 1 files changed, 0 insertions(+), 3 deletions(-) > >> > >> diff --git a/src/pciinit.c b/src/pciinit.c > >> index 25b04ac..6a7a0d2 100644 > >> --- a/src/pciinit.c > >> +++ b/src/pciinit.c > >> @@ -213,9 +213,6 @@ static void pci_bios_init_devices(void) > >> { > >> struct pci_device *pci; > >> foreachpci(pci) { > >> - if (pci_bdf_to_bus(pci->bdf) != 0) > >> - // Only init devices on host bus. > >> - break; > > > > I think this will then assign an incorrect PCI_INTERRUPT_LINE value to > > non root bus devices. > > Attached patch should fix it if I read the specs correctly. I committed this patch. -Kevin
diff --git a/src/pciinit.c b/src/pciinit.c index 52c5b69..e2bdc0c 100644 --- a/src/pciinit.c +++ b/src/pciinit.c @@ -88,9 +88,15 @@ const u8 pci_irqs[4] = { }; // Return the global irq number corresponding to a host bus device irq pin. -static int pci_slot_get_irq(u16 bdf, int pin) +static int pci_slot_get_irq(struct pci_device *pci, int pin) { - int slot_addend = pci_bdf_to_dev(bdf) - 1; + int slot_addend = 0; + + while (pci->parent != NULL) { + slot_addend += pci_bdf_to_dev(pci->bdf); + pci = pci->parent; + } + slot_addend += pci_bdf_to_dev(pci->bdf) - 1; return pci_irqs[(pin - 1 + slot_addend) & 3]; } @@ -211,7 +217,7 @@ static void pci_bios_init_device(struct pci_device *pci) /* map the interrupt */ int pin = pci_config_readb(bdf, PCI_INTERRUPT_PIN); if (pin != 0) - pci_config_writeb(bdf, PCI_INTERRUPT_LINE, pci_slot_get_irq(bdf, pin)); + pci_config_writeb(bdf, PCI_INTERRUPT_LINE, pci_slot_get_irq(pci, pin)); pci_init_device(pci_device_tbl, pci, NULL); }