[PATCH] powerpc: Save device BARs much earlier in the boot sequence
authorLinas Vepstas <linas@linas.org>
Fri, 4 Nov 2005 00:55:19 +0000 (18:55 -0600)
committerPaul Mackerras <paulus@samba.org>
Tue, 10 Jan 2006 04:30:39 +0000 (15:30 +1100)
241-eeh-save-bars-earlier.patch

Save the PCI device bars *before* any PCI probing is done.

Signed-off-by: Linas Vepstas <linas@austin.ibm.com>
Signed-off-by: Paul Mackerras <paulus@samba.org>
(cherry picked from 76c902b919098860f3d4e125f847abcc4cb1782a commit)

arch/powerpc/kernel/rtas_pci.c
arch/powerpc/platforms/pseries/eeh.c
arch/powerpc/platforms/pseries/eeh_cache.c
include/asm-powerpc/pci-bridge.h
include/asm-powerpc/ppc-pci.h

index 45b8109..5579f65 100644 (file)
@@ -72,7 +72,7 @@ static int of_device_available(struct device_node * dn)
         return 0;
 }
 
-static int rtas_read_config(struct pci_dn *pdn, int where, int size, u32 *val)
+int rtas_read_config(struct pci_dn *pdn, int where, int size, u32 *val)
 {
        int returnval = -1;
        unsigned long buid, addr;
index 02bc1f9..9e597cb 100644 (file)
@@ -106,6 +106,8 @@ static DEFINE_PER_CPU(unsigned long, false_positives);
 static DEFINE_PER_CPU(unsigned long, ignored_failures);
 static DEFINE_PER_CPU(unsigned long, slot_resets);
 
+#define IS_BRIDGE(class_code) (((class_code)<<16) == PCI_BASE_CLASS_BRIDGE)
+
 /* --------------------------------------------------------------- */
 /* Below lies the EEH event infrastructure */
 
@@ -620,7 +622,7 @@ void eeh_restore_bars(struct pci_dn *pdn)
        if (!pdn) 
                return;
        
-       if ((pdn->eeh_mode & EEH_MODE_SUPPORTED) && (!pdn->eeh_is_bridge))
+       if ((pdn->eeh_mode & EEH_MODE_SUPPORTED) && !IS_BRIDGE(pdn->class_code))
                __restore_bars (pdn);
 
        dn = pdn->node->child;
@@ -638,18 +640,15 @@ void eeh_restore_bars(struct pci_dn *pdn)
  * PCI devices are added individuallly; but, for the restore,
  * an entire slot is reset at a time.
  */
-void eeh_save_bars(struct pci_dev * pdev, struct pci_dn *pdn)
+static void eeh_save_bars(struct pci_dn *pdn)
 {
        int i;
 
-       if (!pdev || !pdn )
+       if (!pdn )
                return;
        
        for (i = 0; i < 16; i++)
-               pci_read_config_dword(pdev, i * 4, &pdn->config_space[i]);
-
-       if (pdev->hdr_type == PCI_HEADER_TYPE_BRIDGE)
-               pdn->eeh_is_bridge = 1;
+               rtas_read_config(pdn, i * 4, 4, &pdn->config_space[i]);
 }
 
 void
@@ -699,6 +698,7 @@ static void *early_enable_eeh(struct device_node *dn, void *data)
        int enable;
        struct pci_dn *pdn = PCI_DN(dn);
 
+       pdn->class_code = *class_code;
        pdn->eeh_mode = 0;
        pdn->eeh_check_count = 0;
        pdn->eeh_freeze_count = 0;
@@ -781,6 +781,7 @@ static void *early_enable_eeh(struct device_node *dn, void *data)
                       dn->full_name);
        }
 
+       eeh_save_bars(pdn);
        return NULL;
 }
 
@@ -915,7 +916,6 @@ void eeh_add_device_late(struct pci_dev *dev)
        pdn->pcidev = dev;
 
        pci_addr_cache_insert_device (dev);
-       eeh_save_bars(dev, pdn);
 }
 EXPORT_SYMBOL_GPL(eeh_add_device_late);
 
index ff6c938..71b2187 100644 (file)
@@ -304,10 +304,7 @@ void __init pci_addr_cache_build(void)
 
                pci_addr_cache_insert_device(dev);
 
-               /* Save the BAR's; firmware doesn't restore these after EEH reset */
                dn = pci_device_to_OF_node(dev);
-               eeh_save_bars(dev, PCI_DN(dn));
-
                pci_dev_get (dev);  /* matching put is in eeh_remove_device() */
                PCI_DN(dn)->pcidev = dev;
        }
index a81bc36..b0d816f 100644 (file)
@@ -61,9 +61,10 @@ struct pci_controller;
 struct iommu_table;
 
 struct pci_dn {
-       int     busno;                  /* for pci devices */
-       int     bussubno;               /* for pci devices */
-       int     devfn;                  /* for pci devices */
+       int     busno;                  /* pci bus number */
+       int     bussubno;               /* pci subordinate bus number */
+       int     devfn;                  /* pci device and function number */
+       int     class_code;             /* pci device class */
 
 #ifdef CONFIG_PPC_PSERIES
        int     eeh_mode;               /* See eeh.h for possible EEH_MODEs */
@@ -71,7 +72,6 @@ struct pci_dn {
        int     eeh_pe_config_addr; /* new-style partition endpoint address */
        int     eeh_check_count;        /* # times driver ignored error */
        int     eeh_freeze_count;       /* # times this device froze up. */
-       int     eeh_is_bridge;          /* device is pci-to-pci bridge */
 #endif
        int     pci_ext_config_space;   /* for pci devices */
        struct  pci_controller *phb;    /* for pci devices */
index 1a2db61..f80482c 100644 (file)
@@ -58,8 +58,6 @@ void pci_addr_cache_remove_device(struct pci_dev *dev);
 void pci_addr_cache_build(void);
 struct pci_dev *pci_get_device_by_addr(unsigned long addr);
 
-void eeh_save_bars(struct pci_dev * pdev, struct pci_dn *pdn);
-
 /**
  * eeh_slot_error_detail -- record and EEH error condition to the log
  * @severity: 1 if temporary, 2 if permanent failure.
@@ -103,6 +101,7 @@ void eeh_restore_bars(struct pci_dn *);
 void rtas_configure_bridge(struct pci_dn *);
 
 int rtas_write_config(struct pci_dn *, int where, int size, u32 val);
+int rtas_read_config(struct pci_dn *, int where, int size, u32 *val);
 
 /**
  * mark and clear slots: find "partition endpoint" PE and set or