Commit 7684b40c authored by Linas Vepstas's avatar Linas Vepstas Committed by Paul Mackerras
Browse files

[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: default avatarLinas Vepstas <linas@austin.ibm.com>
Signed-off-by: default avatarPaul Mackerras <paulus@samba.org>
(cherry picked from 76c902b919098860f3d4e125f847abcc4cb1782a commit)
parent d177c207
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -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;
+8 −8
Original line number Diff line number Diff line
@@ -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);

+0 −3
Original line number Diff line number Diff line
@@ -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;
	}
+4 −4
Original line number Diff line number Diff line
@@ -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 */
+1 −2
Original line number Diff line number Diff line
@@ -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