[PATCH] powerpc: Save device BARs much earlier in the boot sequence
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)
This commit is contained in:
Родитель
d177c207ba
Коммит
7684b40cb5
|
@ -72,7 +72,7 @@ static int of_device_available(struct device_node * dn)
|
||||||
return 0;
|
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;
|
int returnval = -1;
|
||||||
unsigned long buid, addr;
|
unsigned long buid, addr;
|
||||||
|
|
|
@ -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, ignored_failures);
|
||||||
static DEFINE_PER_CPU(unsigned long, slot_resets);
|
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 */
|
/* Below lies the EEH event infrastructure */
|
||||||
|
|
||||||
|
@ -620,7 +622,7 @@ void eeh_restore_bars(struct pci_dn *pdn)
|
||||||
if (!pdn)
|
if (!pdn)
|
||||||
return;
|
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);
|
__restore_bars (pdn);
|
||||||
|
|
||||||
dn = pdn->node->child;
|
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,
|
* PCI devices are added individuallly; but, for the restore,
|
||||||
* an entire slot is reset at a time.
|
* 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;
|
int i;
|
||||||
|
|
||||||
if (!pdev || !pdn )
|
if (!pdn )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for (i = 0; i < 16; i++)
|
for (i = 0; i < 16; i++)
|
||||||
pci_read_config_dword(pdev, i * 4, &pdn->config_space[i]);
|
rtas_read_config(pdn, i * 4, 4, &pdn->config_space[i]);
|
||||||
|
|
||||||
if (pdev->hdr_type == PCI_HEADER_TYPE_BRIDGE)
|
|
||||||
pdn->eeh_is_bridge = 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -699,6 +698,7 @@ static void *early_enable_eeh(struct device_node *dn, void *data)
|
||||||
int enable;
|
int enable;
|
||||||
struct pci_dn *pdn = PCI_DN(dn);
|
struct pci_dn *pdn = PCI_DN(dn);
|
||||||
|
|
||||||
|
pdn->class_code = *class_code;
|
||||||
pdn->eeh_mode = 0;
|
pdn->eeh_mode = 0;
|
||||||
pdn->eeh_check_count = 0;
|
pdn->eeh_check_count = 0;
|
||||||
pdn->eeh_freeze_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);
|
dn->full_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
eeh_save_bars(pdn);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -915,7 +916,6 @@ void eeh_add_device_late(struct pci_dev *dev)
|
||||||
pdn->pcidev = dev;
|
pdn->pcidev = dev;
|
||||||
|
|
||||||
pci_addr_cache_insert_device (dev);
|
pci_addr_cache_insert_device (dev);
|
||||||
eeh_save_bars(dev, pdn);
|
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(eeh_add_device_late);
|
EXPORT_SYMBOL_GPL(eeh_add_device_late);
|
||||||
|
|
||||||
|
|
|
@ -304,10 +304,7 @@ void __init pci_addr_cache_build(void)
|
||||||
|
|
||||||
pci_addr_cache_insert_device(dev);
|
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);
|
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_dev_get (dev); /* matching put is in eeh_remove_device() */
|
||||||
PCI_DN(dn)->pcidev = dev;
|
PCI_DN(dn)->pcidev = dev;
|
||||||
}
|
}
|
||||||
|
|
|
@ -61,9 +61,10 @@ struct pci_controller;
|
||||||
struct iommu_table;
|
struct iommu_table;
|
||||||
|
|
||||||
struct pci_dn {
|
struct pci_dn {
|
||||||
int busno; /* for pci devices */
|
int busno; /* pci bus number */
|
||||||
int bussubno; /* for pci devices */
|
int bussubno; /* pci subordinate bus number */
|
||||||
int devfn; /* for pci devices */
|
int devfn; /* pci device and function number */
|
||||||
|
int class_code; /* pci device class */
|
||||||
|
|
||||||
#ifdef CONFIG_PPC_PSERIES
|
#ifdef CONFIG_PPC_PSERIES
|
||||||
int eeh_mode; /* See eeh.h for possible EEH_MODEs */
|
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_pe_config_addr; /* new-style partition endpoint address */
|
||||||
int eeh_check_count; /* # times driver ignored error */
|
int eeh_check_count; /* # times driver ignored error */
|
||||||
int eeh_freeze_count; /* # times this device froze up. */
|
int eeh_freeze_count; /* # times this device froze up. */
|
||||||
int eeh_is_bridge; /* device is pci-to-pci bridge */
|
|
||||||
#endif
|
#endif
|
||||||
int pci_ext_config_space; /* for pci devices */
|
int pci_ext_config_space; /* for pci devices */
|
||||||
struct pci_controller *phb; /* for pci devices */
|
struct pci_controller *phb; /* for pci devices */
|
||||||
|
|
|
@ -58,8 +58,6 @@ void pci_addr_cache_remove_device(struct pci_dev *dev);
|
||||||
void pci_addr_cache_build(void);
|
void pci_addr_cache_build(void);
|
||||||
struct pci_dev *pci_get_device_by_addr(unsigned long addr);
|
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
|
* eeh_slot_error_detail -- record and EEH error condition to the log
|
||||||
* @severity: 1 if temporary, 2 if permanent failure.
|
* @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 *);
|
void rtas_configure_bridge(struct pci_dn *);
|
||||||
|
|
||||||
int rtas_write_config(struct pci_dn *, int where, int size, u32 val);
|
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
|
* mark and clear slots: find "partition endpoint" PE and set or
|
||||||
|
|
Загрузка…
Ссылка в новой задаче