Speed up PCI bus scanning by skipping fns 1-7 if fn 0 is not present.
authorMichael Brown <mcb30@etherboot.org>
Sat, 16 Apr 2005 11:42:56 +0000 (11:42 +0000)
committerMichael Brown <mcb30@etherboot.org>
Sat, 16 Apr 2005 11:42:56 +0000 (11:42 +0000)
src/drivers/bus/pci.c
src/include/pci.h

index 44b3a1b..7c4e46a 100644 (file)
@@ -23,18 +23,39 @@ unsigned int pci_max_bus = 0xff;
  * Returns 1 if a device was found, 0 for no device present.
  */
 static int fill_pci_device ( struct pci_device *pci ) {
+       static struct {
+               uint16_t devfn0;
+               int is_present;
+       } cache = { 0, 1 };
        uint32_t l;
        int reg;
 
        /* Check bus is within range */
        if ( PCI_BUS ( pci->busdevfn ) > pci_max_bus )
                return 0;
+
+       /* Check to see if we've cached the result that this is a
+        * non-zero function on a non-existent card.  This is done to
+        * increase scan speed by a factor of 8.
+        */
+       if ( ( PCI_FUNC ( pci->busdevfn ) != 0 ) &&
+            ( PCI_FN0 ( pci->busdevfn ) == cache.devfn0 ) &&
+            ( ! cache.is_present ) ) {
+               return 0;
+       }
        
        /* Check to see if there's anything physically present.
         */
        pci_read_config_dword ( pci, PCI_VENDOR_ID, &l );
        /* some broken boards return 0 if a slot is empty: */
        if ( ( l == 0xffffffff ) || ( l == 0x00000000 ) ) {
+               if ( PCI_FUNC ( pci->busdevfn ) == 0 ) {
+                       /* Don't look for subsequent functions if the
+                        * card itself is not present.
+                        */
+                       cache.devfn0 = pci->busdevfn;
+                       cache.is_present = 0;
+               }
                return 0;
        }
        pci->vendor = l & 0xffff;
@@ -47,7 +68,7 @@ static int fill_pci_device ( struct pci_device *pci ) {
                uint16_t save_busdevfn = pci->busdevfn;
                uint8_t header_type;
 
-               pci->busdevfn &= ~PCI_FUNC ( 0xffff );
+               pci->busdevfn &= PCI_FN0 ( pci->busdevfn );
                pci_read_config_byte ( pci, PCI_HEADER_TYPE, &header_type );
                pci->busdevfn = save_busdevfn;
 
index 9b7fcad..d4e871d 100644 (file)
@@ -252,6 +252,7 @@ struct pci_device {
 #define PCI_BUS(busdevfn)      ( ( (busdevfn) >> 8 ) & 0xff )
 #define PCI_DEV(busdevfn)      ( ( (busdevfn) >> 3 ) & 0x1f )
 #define PCI_FUNC(busdevfn)      ( (busdevfn) & 0x07 )
+#define PCI_FN0(busdevfn)      ( (busdevfn) & 0xfff8 )
 
 /*
  * An individual PCI device identified by vendor and device IDs