diff mbox

[SeaBIOS,seabios,1/5] pci: init all devices

Message ID 4FA3F72E.7080103@redhat.com
State New
Headers show

Commit Message

Gerd Hoffmann May 4, 2012, 3:35 p.m. UTC
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.
Untested though, review appreciated.

cheers,
  Gerd
From a36868ea1b32978244624a62ce7742346cbf5e50 Mon Sep 17 00:00:00 2001
From: Gerd Hoffmann <kraxel@redhat.com>
Date: Fri, 4 May 2012 17:33:36 +0200
Subject: [PATCH] pci: handle bridge irq mapping

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 src/pciinit.c |   12 +++++++++---
 1 files changed, 9 insertions(+), 3 deletions(-)

Comments

Kevin O'Connor May 5, 2012, 12:10 a.m. UTC | #1
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
Kevin O'Connor May 12, 2012, 6:16 p.m. UTC | #2
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 mbox

Patch

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);
 }