Properly detect muliple PCI root brings in L4Re's io process

Christian Ehrhardt Christian_Ehrhardt at genua.de
Wed Jun 1 17:20:32 CEST 2011


Hi,

I tried to run fiasco and L4Linux on an SMP machine that features two
idenpendent PCI root bridges. Currently, the io process fails to scan
the bus connected to the second bridge.

It properly detects that two PCI root bridges are present and creates
two seperate Pci_port_root_bridge objects. However, it fails to
initialize the Pci_bridge::num field properly. As a result, the io
process scans the first bus twice. This causes major havoc as PCI
devices on the second bus don't show up in L4Linux at all and devices
on the first bus are detected twice.

According to http://www.acpi.info/acpi_faq.htm the ACPI structures should
contain a _BBN method to detect the bus number of both root busses.
The following patch uses this method to detect and set the Pci_bridge::num
field properly.

A patch to fix this is provided below. With this patch NICs on both PCI
busses are detected and work properly on the hardware in question.

As always comments are appreciated.

      regards     Christian


The contributions made by this patch are licensed under the MIT license
(http://www.opensource.org/licenses/mit-license.php).

diff --git a/src/l4/pkg/io/server/src/acpi.cc b/src/l4/pkg/io/server/src/acpi.cc
index f76c768..4179c4e 100644
--- a/src/l4/pkg/io/server/src/acpi.cc
+++ b/src/l4/pkg/io/server/src/acpi.cc
@@ -572,9 +572,25 @@ discover_pre_cb(ACPI_HANDLE obj, UINT32 nl, void *ctxt, void **)
   //AcpiUtReleaseMutex(ACPI_MTX_NAMESPACE);
 
   // hm, this seems very specific for PCI
+  /*
+   * Systems with multiple PCI root bridges must provide the PCI bus
+   * number of each bus via the _BBN method.
+   */
   if (pci_rb)
     {
-      d_printf(DBG_DEBUG, "Found PCI root bridge...\n");
+      ACPI_INTEGER pci_int;
+      bool have_bbn = false;
+
+      if (ACPI_SUCCESS(AcpiUtEvaluateNumericObject((char*)METHOD_NAME__BBN,
+	node, &pci_int)))
+	{
+	  d_printf(DBG_DEBUG, "PCI root bridge with BBN=%llx...\n", pci_int);
+	  have_bbn = true;
+	}
+      else
+	{
+	  d_printf(DBG_DEBUG, "Found PCI root bridge without BBN...\n");
+	}
       if (Pci_root_bridge *rb = pci_root_bridge(0))
 	{
 	  if (rb->host())
@@ -582,9 +598,13 @@ discover_pre_cb(ACPI_HANDLE obj, UINT32 nl, void *ctxt, void **)
 	      // we found a second root bridge
 	      // create a new root pridge instance
 	      rb = new Pci_port_root_bridge(nd);
+	      if (!have_bbn)
+		d_printf(DBG_ERR, "ERROR: Multiple root bridges without BBN\n");
 	    }
 	  else
 	    rb->set_host(nd);
+	  if (have_bbn)
+	    rb->num = pci_int;
 
 	  nd->set_discover_bus_if(rb);
 	}




More information about the l4-hackers mailing list