Commit 428d4d65 authored by Michael Ellerman's avatar Michael Ellerman

Merge branch 'next-eeh' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc into next

parents 28ea605c 027fa02f
...@@ -8,6 +8,9 @@ ...@@ -8,6 +8,9 @@
struct dma_map_ops; struct dma_map_ops;
struct device_node; struct device_node;
#ifdef CONFIG_PPC64
struct pci_dn;
#endif
/* /*
* Arch extensions to struct device. * Arch extensions to struct device.
...@@ -34,6 +37,9 @@ struct dev_archdata { ...@@ -34,6 +37,9 @@ struct dev_archdata {
#ifdef CONFIG_SWIOTLB #ifdef CONFIG_SWIOTLB
dma_addr_t max_direct_dma_addr; dma_addr_t max_direct_dma_addr;
#endif #endif
#ifdef CONFIG_PPC64
struct pci_dn *pci_data;
#endif
#ifdef CONFIG_EEH #ifdef CONFIG_EEH
struct eeh_dev *edev; struct eeh_dev *edev;
#endif #endif
......
...@@ -29,7 +29,7 @@ ...@@ -29,7 +29,7 @@
struct pci_dev; struct pci_dev;
struct pci_bus; struct pci_bus;
struct device_node; struct pci_dn;
#ifdef CONFIG_EEH #ifdef CONFIG_EEH
...@@ -136,14 +136,14 @@ struct eeh_dev { ...@@ -136,14 +136,14 @@ struct eeh_dev {
struct eeh_pe *pe; /* Associated PE */ struct eeh_pe *pe; /* Associated PE */
struct list_head list; /* Form link list in the PE */ struct list_head list; /* Form link list in the PE */
struct pci_controller *phb; /* Associated PHB */ struct pci_controller *phb; /* Associated PHB */
struct device_node *dn; /* Associated device node */ struct pci_dn *pdn; /* Associated PCI device node */
struct pci_dev *pdev; /* Associated PCI device */ struct pci_dev *pdev; /* Associated PCI device */
struct pci_bus *bus; /* PCI bus for partial hotplug */ struct pci_bus *bus; /* PCI bus for partial hotplug */
}; };
static inline struct device_node *eeh_dev_to_of_node(struct eeh_dev *edev) static inline struct pci_dn *eeh_dev_to_pdn(struct eeh_dev *edev)
{ {
return edev ? edev->dn : NULL; return edev ? edev->pdn : NULL;
} }
static inline struct pci_dev *eeh_dev_to_pci_dev(struct eeh_dev *edev) static inline struct pci_dev *eeh_dev_to_pci_dev(struct eeh_dev *edev)
...@@ -200,8 +200,7 @@ struct eeh_ops { ...@@ -200,8 +200,7 @@ struct eeh_ops {
char *name; char *name;
int (*init)(void); int (*init)(void);
int (*post_init)(void); int (*post_init)(void);
void* (*of_probe)(struct device_node *dn, void *flag); void* (*probe)(struct pci_dn *pdn, void *data);
int (*dev_probe)(struct pci_dev *dev, void *flag);
int (*set_option)(struct eeh_pe *pe, int option); int (*set_option)(struct eeh_pe *pe, int option);
int (*get_pe_addr)(struct eeh_pe *pe); int (*get_pe_addr)(struct eeh_pe *pe);
int (*get_state)(struct eeh_pe *pe, int *state); int (*get_state)(struct eeh_pe *pe, int *state);
...@@ -211,10 +210,10 @@ struct eeh_ops { ...@@ -211,10 +210,10 @@ struct eeh_ops {
int (*configure_bridge)(struct eeh_pe *pe); int (*configure_bridge)(struct eeh_pe *pe);
int (*err_inject)(struct eeh_pe *pe, int type, int func, int (*err_inject)(struct eeh_pe *pe, int type, int func,
unsigned long addr, unsigned long mask); unsigned long addr, unsigned long mask);
int (*read_config)(struct device_node *dn, int where, int size, u32 *val); int (*read_config)(struct pci_dn *pdn, int where, int size, u32 *val);
int (*write_config)(struct device_node *dn, int where, int size, u32 val); int (*write_config)(struct pci_dn *pdn, int where, int size, u32 val);
int (*next_error)(struct eeh_pe **pe); int (*next_error)(struct eeh_pe **pe);
int (*restore_config)(struct device_node *dn); int (*restore_config)(struct pci_dn *pdn);
}; };
extern int eeh_subsystem_flags; extern int eeh_subsystem_flags;
...@@ -272,7 +271,7 @@ void eeh_pe_restore_bars(struct eeh_pe *pe); ...@@ -272,7 +271,7 @@ void eeh_pe_restore_bars(struct eeh_pe *pe);
const char *eeh_pe_loc_get(struct eeh_pe *pe); const char *eeh_pe_loc_get(struct eeh_pe *pe);
struct pci_bus *eeh_pe_bus_get(struct eeh_pe *pe); struct pci_bus *eeh_pe_bus_get(struct eeh_pe *pe);
void *eeh_dev_init(struct device_node *dn, void *data); void *eeh_dev_init(struct pci_dn *pdn, void *data);
void eeh_dev_phb_init_dynamic(struct pci_controller *phb); void eeh_dev_phb_init_dynamic(struct pci_controller *phb);
int eeh_init(void); int eeh_init(void);
int __init eeh_ops_register(struct eeh_ops *ops); int __init eeh_ops_register(struct eeh_ops *ops);
...@@ -280,8 +279,8 @@ int __exit eeh_ops_unregister(const char *name); ...@@ -280,8 +279,8 @@ int __exit eeh_ops_unregister(const char *name);
int eeh_check_failure(const volatile void __iomem *token); int eeh_check_failure(const volatile void __iomem *token);
int eeh_dev_check_failure(struct eeh_dev *edev); int eeh_dev_check_failure(struct eeh_dev *edev);
void eeh_addr_cache_build(void); void eeh_addr_cache_build(void);
void eeh_add_device_early(struct device_node *); void eeh_add_device_early(struct pci_dn *);
void eeh_add_device_tree_early(struct device_node *); void eeh_add_device_tree_early(struct pci_dn *);
void eeh_add_device_late(struct pci_dev *); void eeh_add_device_late(struct pci_dev *);
void eeh_add_device_tree_late(struct pci_bus *); void eeh_add_device_tree_late(struct pci_bus *);
void eeh_add_sysfs_files(struct pci_bus *); void eeh_add_sysfs_files(struct pci_bus *);
...@@ -323,7 +322,7 @@ static inline int eeh_init(void) ...@@ -323,7 +322,7 @@ static inline int eeh_init(void)
return 0; return 0;
} }
static inline void *eeh_dev_init(struct device_node *dn, void *data) static inline void *eeh_dev_init(struct pci_dn *pdn, void *data)
{ {
return NULL; return NULL;
} }
...@@ -339,9 +338,9 @@ static inline int eeh_check_failure(const volatile void __iomem *token) ...@@ -339,9 +338,9 @@ static inline int eeh_check_failure(const volatile void __iomem *token)
static inline void eeh_addr_cache_build(void) { } static inline void eeh_addr_cache_build(void) { }
static inline void eeh_add_device_early(struct device_node *dn) { } static inline void eeh_add_device_early(struct pci_dn *pdn) { }
static inline void eeh_add_device_tree_early(struct device_node *dn) { } static inline void eeh_add_device_tree_early(struct pci_dn *pdn) { }
static inline void eeh_add_device_late(struct pci_dev *dev) { } static inline void eeh_add_device_late(struct pci_dev *dev) { }
......
...@@ -125,7 +125,7 @@ struct machdep_calls { ...@@ -125,7 +125,7 @@ struct machdep_calls {
unsigned int (*get_irq)(void); unsigned int (*get_irq)(void);
/* PCI stuff */ /* PCI stuff */
/* Called after scanning the bus, before allocating resources */ /* Called after allocating resources */
void (*pcibios_fixup)(void); void (*pcibios_fixup)(void);
int (*pci_probe_mode)(struct pci_bus *); int (*pci_probe_mode)(struct pci_bus *);
void (*pci_irq_fixup)(struct pci_dev *dev); void (*pci_irq_fixup)(struct pci_dev *dev);
......
...@@ -89,6 +89,7 @@ struct pci_controller { ...@@ -89,6 +89,7 @@ struct pci_controller {
#ifdef CONFIG_PPC64 #ifdef CONFIG_PPC64
unsigned long buid; unsigned long buid;
struct pci_dn *pci_data;
#endif /* CONFIG_PPC64 */ #endif /* CONFIG_PPC64 */
void *private_data; void *private_data;
...@@ -154,9 +155,15 @@ static inline int isa_vaddr_is_ioport(void __iomem *address) ...@@ -154,9 +155,15 @@ static inline int isa_vaddr_is_ioport(void __iomem *address)
struct iommu_table; struct iommu_table;
struct pci_dn { struct pci_dn {
int flags;
int busno; /* pci bus number */ int busno; /* pci bus number */
int devfn; /* pci device and function number */ int devfn; /* pci device and function number */
int vendor_id; /* Vendor ID */
int device_id; /* Device ID */
int class_code; /* Device class code */
struct pci_dn *parent;
struct pci_controller *phb; /* for pci devices */ struct pci_controller *phb; /* for pci devices */
struct iommu_table *iommu_table; /* for phb's or bridges */ struct iommu_table *iommu_table; /* for phb's or bridges */
struct device_node *node; /* back-pointer to the device_node */ struct device_node *node; /* back-pointer to the device_node */
...@@ -171,14 +178,17 @@ struct pci_dn { ...@@ -171,14 +178,17 @@ struct pci_dn {
#ifdef CONFIG_PPC_POWERNV #ifdef CONFIG_PPC_POWERNV
int pe_number; int pe_number;
#endif #endif
struct list_head child_list;
struct list_head list;
}; };
/* Get the pointer to a device_node's pci_dn */ /* Get the pointer to a device_node's pci_dn */
#define PCI_DN(dn) ((struct pci_dn *) (dn)->data) #define PCI_DN(dn) ((struct pci_dn *) (dn)->data)
extern struct pci_dn *pci_get_pdn_by_devfn(struct pci_bus *bus,
int devfn);
extern struct pci_dn *pci_get_pdn(struct pci_dev *pdev); extern struct pci_dn *pci_get_pdn(struct pci_dev *pdev);
extern void *update_dn_pci_info(struct device_node *dn, void *data);
extern void * update_dn_pci_info(struct device_node *dn, void *data);
static inline int pci_device_from_OF_node(struct device_node *np, static inline int pci_device_from_OF_node(struct device_node *np,
u8 *bus, u8 *devfn) u8 *bus, u8 *devfn)
...@@ -191,20 +201,12 @@ static inline int pci_device_from_OF_node(struct device_node *np, ...@@ -191,20 +201,12 @@ static inline int pci_device_from_OF_node(struct device_node *np,
} }
#if defined(CONFIG_EEH) #if defined(CONFIG_EEH)
static inline struct eeh_dev *of_node_to_eeh_dev(struct device_node *dn) static inline struct eeh_dev *pdn_to_eeh_dev(struct pci_dn *pdn)
{ {
/* return pdn ? pdn->edev : NULL;
* For those OF nodes whose parent isn't PCI bridge, they
* don't have PCI_DN actually. So we have to skip them for
* any EEH operations.
*/
if (!dn || !PCI_DN(dn))
return NULL;
return PCI_DN(dn)->edev;
} }
#else #else
#define of_node_to_eeh_dev(x) (NULL) #define pdn_to_eeh_dev(x) (NULL)
#endif #endif
/** Find the bus corresponding to the indicated device node */ /** Find the bus corresponding to the indicated device node */
......
...@@ -33,9 +33,14 @@ extern struct pci_dev *isa_bridge_pcidev; /* may be NULL if no ISA bus */ ...@@ -33,9 +33,14 @@ extern struct pci_dev *isa_bridge_pcidev; /* may be NULL if no ISA bus */
/* PCI device_node operations */ /* PCI device_node operations */
struct device_node; struct device_node;
struct pci_dn;
typedef void *(*traverse_func)(struct device_node *me, void *data); typedef void *(*traverse_func)(struct device_node *me, void *data);
void *traverse_pci_devices(struct device_node *start, traverse_func pre, void *traverse_pci_devices(struct device_node *start, traverse_func pre,
void *data); void *data);
void *traverse_pci_dn(struct pci_dn *root,
void *(*fn)(struct pci_dn *, void *),
void *data);
extern void pci_devs_phb_init(void); extern void pci_devs_phb_init(void);
extern void pci_devs_phb_init_dynamic(struct pci_controller *phb); extern void pci_devs_phb_init_dynamic(struct pci_controller *phb);
......
This diff is collapsed.
...@@ -171,30 +171,27 @@ eeh_addr_cache_insert(struct pci_dev *dev, unsigned long alo, ...@@ -171,30 +171,27 @@ eeh_addr_cache_insert(struct pci_dev *dev, unsigned long alo,
static void __eeh_addr_cache_insert_dev(struct pci_dev *dev) static void __eeh_addr_cache_insert_dev(struct pci_dev *dev)
{ {
struct device_node *dn; struct pci_dn *pdn;
struct eeh_dev *edev; struct eeh_dev *edev;
int i; int i;
dn = pci_device_to_OF_node(dev); pdn = pci_get_pdn_by_devfn(dev->bus, dev->devfn);
if (!dn) { if (!pdn) {
pr_warn("PCI: no pci dn found for dev=%s\n", pr_warn("PCI: no pci dn found for dev=%s\n",
pci_name(dev)); pci_name(dev));
return; return;
} }
edev = of_node_to_eeh_dev(dn); edev = pdn_to_eeh_dev(pdn);
if (!edev) { if (!edev) {
pr_warn("PCI: no EEH dev found for dn=%s\n", pr_warn("PCI: no EEH dev found for %s\n",
dn->full_name); pci_name(dev));
return; return;
} }
/* Skip any devices for which EEH is not enabled. */ /* Skip any devices for which EEH is not enabled. */
if (!edev->pe) { if (!edev->pe) {
#ifdef DEBUG dev_dbg(&dev->dev, "EEH: Skip building address cache\n");
pr_info("PCI: skip building address cache for=%s - %s\n",
pci_name(dev), dn->full_name);
#endif
return; return;
} }
...@@ -282,18 +279,18 @@ void eeh_addr_cache_rmv_dev(struct pci_dev *dev) ...@@ -282,18 +279,18 @@ void eeh_addr_cache_rmv_dev(struct pci_dev *dev)
*/ */
void eeh_addr_cache_build(void) void eeh_addr_cache_build(void)
{ {
struct device_node *dn; struct pci_dn *pdn;
struct eeh_dev *edev; struct eeh_dev *edev;
struct pci_dev *dev = NULL; struct pci_dev *dev = NULL;
spin_lock_init(&pci_io_addr_cache_root.piar_lock); spin_lock_init(&pci_io_addr_cache_root.piar_lock);
for_each_pci_dev(dev) { for_each_pci_dev(dev) {
dn = pci_device_to_OF_node(dev); pdn = pci_get_pdn_by_devfn(dev->bus, dev->devfn);
if (!dn) if (!pdn)
continue; continue;
edev = of_node_to_eeh_dev(dn); edev = pdn_to_eeh_dev(pdn);
if (!edev) if (!edev)
continue; continue;
......
...@@ -43,13 +43,13 @@ ...@@ -43,13 +43,13 @@
/** /**
* eeh_dev_init - Create EEH device according to OF node * eeh_dev_init - Create EEH device according to OF node
* @dn: device node * @pdn: PCI device node
* @data: PHB * @data: PHB
* *
* It will create EEH device according to the given OF node. The function * It will create EEH device according to the given OF node. The function
* might be called by PCI emunation, DR, PHB hotplug. * might be called by PCI emunation, DR, PHB hotplug.
*/ */
void *eeh_dev_init(struct device_node *dn, void *data) void *eeh_dev_init(struct pci_dn *pdn, void *data)
{ {
struct pci_controller *phb = data; struct pci_controller *phb = data;
struct eeh_dev *edev; struct eeh_dev *edev;
...@@ -63,8 +63,8 @@ void *eeh_dev_init(struct device_node *dn, void *data) ...@@ -63,8 +63,8 @@ void *eeh_dev_init(struct device_node *dn, void *data)
} }
/* Associate EEH device with OF node */ /* Associate EEH device with OF node */
PCI_DN(dn)->edev = edev; pdn->edev = edev;
edev->dn = dn; edev->pdn = pdn;
edev->phb = phb; edev->phb = phb;
INIT_LIST_HEAD(&edev->list); INIT_LIST_HEAD(&edev->list);
...@@ -80,16 +80,16 @@ void *eeh_dev_init(struct device_node *dn, void *data) ...@@ -80,16 +80,16 @@ void *eeh_dev_init(struct device_node *dn, void *data)
*/ */
void eeh_dev_phb_init_dynamic(struct pci_controller *phb) void eeh_dev_phb_init_dynamic(struct pci_controller *phb)
{ {
struct device_node *dn = phb->dn; struct pci_dn *root = phb->pci_data;
/* EEH PE for PHB */ /* EEH PE for PHB */
eeh_phb_pe_create(phb); eeh_phb_pe_create(phb);
/* EEH device for PHB */ /* EEH device for PHB */
eeh_dev_init(dn, phb); eeh_dev_init(root, phb);
/* EEH devices for children OF nodes */ /* EEH devices for children OF nodes */
traverse_pci_devices(dn, eeh_dev_init, phb); traverse_pci_dn(root, eeh_dev_init, phb);
} }
/** /**
......
...@@ -83,28 +83,6 @@ static inline void eeh_pcid_put(struct pci_dev *pdev) ...@@ -83,28 +83,6 @@ static inline void eeh_pcid_put(struct pci_dev *pdev)
module_put(pdev->driver->driver.owner); module_put(pdev->driver->driver.owner);
} }
#if 0
static void print_device_node_tree(struct pci_dn *pdn, int dent)
{
int i;
struct device_node *pc;
if (!pdn)
return;
for (i = 0; i < dent; i++)
printk(" ");
printk("dn=%s mode=%x \tcfg_addr=%x pe_addr=%x \tfull=%s\n",
pdn->node->name, pdn->eeh_mode, pdn->eeh_config_addr,
pdn->eeh_pe_config_addr, pdn->node->full_name);
dent += 3;
pc = pdn->node->child;
while (pc) {
print_device_node_tree(PCI_DN(pc), dent);
pc = pc->sibling;
}
}
#endif
/** /**
* eeh_disable_irq - Disable interrupt for the recovering device * eeh_disable_irq - Disable interrupt for the recovering device
* @dev: PCI device * @dev: PCI device
......
...@@ -291,27 +291,25 @@ struct eeh_pe *eeh_pe_get(struct eeh_dev *edev) ...@@ -291,27 +291,25 @@ struct eeh_pe *eeh_pe_get(struct eeh_dev *edev)
*/ */
static struct eeh_pe *eeh_pe_get_parent(struct eeh_dev *edev) static struct eeh_pe *eeh_pe_get_parent(struct eeh_dev *edev)
{ {
struct device_node *dn;
struct eeh_dev *parent; struct eeh_dev *parent;
struct pci_dn *pdn = eeh_dev_to_pdn(edev);
/* /*
* It might have the case for the indirect parent * It might have the case for the indirect parent
* EEH device already having associated PE, but * EEH device already having associated PE, but
* the direct parent EEH device doesn't have yet. * the direct parent EEH device doesn't have yet.
*/ */
dn = edev->dn->parent; pdn = pdn ? pdn->parent : NULL;
while (dn) { while (pdn) {
/* We're poking out of PCI territory */ /* We're poking out of PCI territory */
if (!PCI_DN(dn)) return NULL; parent = pdn_to_eeh_dev(pdn);
if (!parent)
parent = of_node_to_eeh_dev(dn); return NULL;
/* We're poking out of PCI territory */
if (!parent) return NULL;
if (parent->pe) if (parent->pe)
return parent->pe; return parent->pe;
dn = dn->parent; pdn = pdn->parent;
} }
return NULL; return NULL;
...@@ -330,6 +328,13 @@ int eeh_add_to_parent_pe(struct eeh_dev *edev) ...@@ -330,6 +328,13 @@ int eeh_add_to_parent_pe(struct eeh_dev *edev)
{ {
struct eeh_pe *pe, *parent; struct eeh_pe *pe, *parent;
/* Check if the PE number is valid */
if (!eeh_has_flag(EEH_VALID_PE_ZERO) && !edev->pe_config_addr) {
pr_err("%s: Invalid PE#0 for edev 0x%x on PHB#%d\n",
__func__, edev->config_addr, edev->phb->global_number);
return -EINVAL;
}
/* /*
* Search the PE has been existing or not according * Search the PE has been existing or not according
* to the PE address. If that has been existing, the * to the PE address. If that has been existing, the
...@@ -338,21 +343,18 @@ int eeh_add_to_parent_pe(struct eeh_dev *edev) ...@@ -338,21 +343,18 @@ int eeh_add_to_parent_pe(struct eeh_dev *edev)
*/ */
pe = eeh_pe_get(edev); pe = eeh_pe_get(edev);
if (pe && !(pe->type & EEH_PE_INVALID)) { if (pe && !(pe->type & EEH_PE_INVALID)) {
if (!edev->pe_config_addr) {
pr_err("%s: PE with addr 0x%x already exists\n",
__func__, edev->config_addr);
return -EEXIST;
}
/* Mark the PE as type of PCI bus */ /* Mark the PE as type of PCI bus */
pe->type = EEH_PE_BUS; pe->type = EEH_PE_BUS;
edev->pe = pe; edev->pe = pe;
/* Put the edev to PE */ /* Put the edev to PE */
list_add_tail(&edev->list, &pe->edevs); list_add_tail(&edev->list, &pe->edevs);
pr_debug("EEH: Add %s to Bus PE#%x\n", pr_debug("EEH: Add %04x:%02x:%02x.%01x to Bus PE#%x\n",
edev->dn->full_name, pe->addr); edev->phb->global_number,
edev->config_addr >> 8,
PCI_SLOT(edev->config_addr & 0xFF),
PCI_FUNC(edev->config_addr & 0xFF),
pe->addr);
return 0; return 0;
} else if (pe && (pe->type & EEH_PE_INVALID)) { } else if (pe && (pe->type & EEH_PE_INVALID)) {
list_add_tail(&edev->list, &pe->edevs); list_add_tail(&edev->list, &pe->edevs);
...@@ -368,9 +370,14 @@ int eeh_add_to_parent_pe(struct eeh_dev *edev) ...@@ -368,9 +370,14 @@ int eeh_add_to_parent_pe(struct eeh_dev *edev)
parent->type &= ~(EEH_PE_INVALID | EEH_PE_KEEP); parent->type &= ~(EEH_PE_INVALID | EEH_PE_KEEP);
parent = parent->parent; parent = parent->parent;
} }
pr_debug("EEH: Add %s to Device PE#%x, Parent PE#%x\n",
edev->dn->full_name, pe->addr, pe->parent->addr);
pr_debug("EEH: Add %04x:%02x:%02x.%01x to Device "
"PE#%x, Parent PE#%x\n",
edev->phb->global_number,
edev->config_addr >> 8,
PCI_SLOT(edev->config_addr & 0xFF),
PCI_FUNC(edev->config_addr & 0xFF),
pe->addr, pe->parent->addr);
return 0; return 0;
} }
...@@ -409,8 +416,13 @@ int eeh_add_to_parent_pe(struct eeh_dev *edev) ...@@ -409,8 +416,13 @@ int eeh_add_to_parent_pe(struct eeh_dev *edev)
list_add_tail(&pe->child, &parent->child_list); list_add_tail(&pe->child, &parent->child_list);
list_add_tail(&edev->list, &pe->edevs); list_add_tail(&edev->list, &pe->edevs);
edev->pe = pe; edev->pe = pe;
pr_debug("EEH: Add %s to Device PE#%x, Parent PE#%x\n", pr_debug("EEH: Add %04x:%02x:%02x.%01x to "
edev->dn->full_name, pe->addr, pe->parent->addr); "Device PE#%x, Parent PE#%x\n",
edev->phb->global_number,
edev->config_addr >> 8,
PCI_SLOT(edev->config_addr & 0xFF),
PCI_FUNC(edev->config_addr & 0xFF),
pe->addr, pe->parent->addr);
return 0; return 0;
} }
...@@ -430,8 +442,11 @@ int eeh_rmv_from_parent_pe(struct eeh_dev *edev) ...@@ -430,8 +442,11 @@ int eeh_rmv_from_parent_pe(struct eeh_dev *edev)
int cnt; int cnt;
if (!edev->pe) { if (!edev->pe) {
pr_debug("%s: No PE found for EEH device %s\n", pr_debug("%s: No PE found for device %04x:%02x:%02x.%01x\n",
__func__, edev->dn->full_name); __func__, edev->phb->global_number,
edev->config_addr >> 8,
PCI_SLOT(edev->config_addr & 0xFF),
PCI_FUNC(edev->config_addr & 0xFF));
return -EEXIST; return -EEXIST;
} }
...@@ -653,9 +668,9 @@ void eeh_pe_state_clear(struct eeh_pe *pe, int state) ...@@ -653,9 +668,9 @@ void eeh_pe_state_clear(struct eeh_pe *pe, int state)
* blocked on normal path during the stage. So we need utilize * blocked on normal path during the stage. So we need utilize
* eeh operations, which is always permitted. * eeh operations, which is always permitted.
*/ */
static void eeh_bridge_check_link(struct eeh_dev *edev, static void eeh_bridge_check_link(struct eeh_dev *edev)
struct device_node *dn)
{ {
struct pci_dn *pdn = eeh_dev_to_pdn(edev);
int cap; int cap;
uint32_t val; uint32_t val;
int timeout = 0; int timeout = 0;
...@@ -675,32 +690,32 @@ static void eeh_bridge_check_link(struct eeh_dev *edev, ...@@ -675,32 +690,32 @@ static void eeh_bridge_check_link(struct eeh_dev *edev,
/* Check slot status */ /* Check slot status */
cap = edev->pcie_cap; cap = edev->pcie_cap;
eeh_ops->read_config(dn, cap + PCI_EXP_SLTSTA, 2, &val); eeh_ops->read_config(pdn, cap + PCI_EXP_SLTSTA, 2, &val);
if (!(val & PCI_EXP_SLTSTA_PDS)) { if (!(val & PCI_EXP_SLTSTA_PDS)) {
pr_debug(" No card in the slot (0x%04x) !\n", val); pr_debug(" No card in the slot (0x%04x) !\n", val);
return; return;
} }
/* Check power status if we have the capability */ /* Check power status if we have the capability */
eeh_ops->read_config(dn, cap + PCI_EXP_SLTCAP, 2, &val); eeh_ops->read_config(pdn, cap + PCI_EXP_SLTCAP, 2, &val);
if (val & PCI_EXP_SLTCAP_PCP) { if (val & PCI_EXP_SLTCAP_PCP) {
eeh_ops->read_config(dn, cap + PCI_EXP_SLTCTL, 2, &val); eeh_ops->read_config(pdn, cap + PCI_EXP_SLTCTL, 2, &val);
if (val & PCI_EXP_SLTCTL_PCC) { if (val & PCI_EXP_SLTCTL_PCC) {
pr_debug(" In power-off state, power it on ...\n"); pr_debug(" In power-off state, power it on ...\n");
val &= ~(PCI_EXP_SLTCTL_PCC | PCI_EXP_SLTCTL_PIC); val &= ~(PCI_EXP_SLTCTL_PCC | PCI_EXP_SLTCTL_PIC);
val |= (0x0100 & PCI_EXP_SLTCTL_PIC); val |= (0x0100 & PCI_EXP_SLTCTL_PIC);
eeh_ops->write_config(dn, cap + PCI_EXP_SLTCTL, 2, val); eeh_ops->write_config(pdn, cap + PCI_EXP_SLTCTL, 2, val);
msleep(2 * 1000); msleep(2 * 1000);
} }
} }
/* Enable link */ /* Enable link */
eeh_ops->read_config(dn, cap + PCI_EXP_LNKCTL, 2, &val); eeh_ops->read_config(pdn, cap + PCI_EXP_LNKCTL, 2, &val);
val &= ~PCI_EXP_LNKCTL_LD; val &= ~PCI_EXP_LNKCTL_LD;
eeh_ops->write_config(dn, cap + PCI_EXP_LNKCTL, 2, val); eeh_ops->write_config(pdn, cap + PCI_EXP_LNKCTL, 2, val);
/* Check link */ /* Check link */
eeh_ops->read_config(dn, cap + PCI_EXP_LNKCAP, 4, &val); eeh_ops->read_config(pdn, cap + PCI_EXP_LNKCAP, 4, &val);
if (!(val & PCI_EXP_LNKCAP_DLLLARC)) { if (!(val & PCI_EXP_LNKCAP_DLLLARC)) {
pr_debug(" No link reporting capability (0x%08x) \n", val); pr_debug(" No link reporting capability (0x%08x) \n", val);
msleep(1000); msleep(1000);
...@@ -713,7 +728,7 @@ static void eeh_bridge_check_link(struct eeh_dev *edev, ...@@ -713,7 +728,7 @@ static void eeh_bridge_check_link(struct eeh_dev *edev,
msleep(20); msleep(20);
timeout += 20; timeout += 20;
eeh_ops->read_config(dn, cap + PCI_EXP_LNKSTA, 2, &val); eeh_ops->read_config(pdn, cap + PCI_EXP_LNKSTA, 2, &val);
if (val & PCI_EXP_LNKSTA_DLLLA) if (val & PCI_EXP_LNKSTA_DLLLA)
break; break;
} }
...@@ -728,9 +743,9 @@ static void eeh_bridge_check_link(struct eeh_dev *edev, ...@@ -728,9 +743,9 @@ static void eeh_bridge_check_link(struct eeh_dev *edev,
#define BYTE_SWAP(OFF) (8*((OFF)/4)+3-(OFF)) #define BYTE_SWAP(OFF) (8*((OFF)/4)+3-(OFF))
#define SAVED_BYTE(OFF) (((u8 *)(edev->config_space))[BYTE_SWAP(OFF)]) #define SAVED_BYTE(OFF) (((u8 *)(edev->config_space))[BYTE_SWAP(OFF)])
static void eeh_restore_bridge_bars(struct eeh_dev *edev, static void eeh_restore_bridge_bars(struct eeh_dev *edev)
struct device_node *dn)
{ {
struct pci_dn *pdn = eeh_dev_to_pdn(edev);
int i; int i;
/* /*
...@@ -738,49 +753,49 @@ static void eeh_restore_bridge_bars(struct eeh_dev *edev, ...@@ -738,49 +753,49 @@ static void eeh_restore_bridge_bars(struct eeh_dev *edev,
* Bus numbers and windows: 0x18 - 0x30 * Bus numbers and windows: 0x18 - 0x30
*/ */
for (i = 4; i < 13; i++) for (i = 4; i < 13; i++)
eeh_ops->write_config(dn, i*4, 4, edev->config_space[i]); eeh_ops->write_config(pdn, i*4, 4, edev->config_space[i]);
/* Rom: 0x38 */ /* Rom: 0x38 */
eeh_ops->write_config(dn, 14*4, 4, edev->config_space[14]); eeh_ops->write_config(pdn, 14*4, 4, edev->config_space[14]);
/* Cache line & Latency timer: 0xC 0xD */ /* Cache line & Latency timer: 0xC 0xD */
eeh_ops->write_config(dn, PCI_CACHE_LINE_SIZE, 1, eeh_ops->write_config(pdn, PCI_CACHE_LINE_SIZE, 1,
SAVED_BYTE(PCI_CACHE_LINE_SIZE)); SAVED_BYTE(PCI_CACHE_LINE_SIZE));
eeh_ops->write_config(dn, PCI_LATENCY_TIMER, 1, eeh_ops->write_config(pdn, PCI_LATENCY_TIMER, 1,
SAVED_BYTE(PCI_LATENCY_TIMER)); SAVED_BYTE(PCI_LATENCY_TIMER));
/* Max latency, min grant, interrupt ping and line: 0x3C */ /* Max latency, min grant, interrupt ping and line: 0x3C */
eeh_ops->write_config(dn, 15*4, 4, edev->config_space[15]); eeh_ops->write_config(pdn, 15*4, 4, edev->config_space[15]);
/* PCI Command: 0x4 */ /* PCI Command: 0x4 */
eeh_ops->write_config(dn, PCI_COMMAND, 4, edev->config_space[1]); eeh_ops->write_config(pdn, PCI_COMMAND, 4, edev->config_space[1]);
/* Check the PCIe link is ready */ /* Check the PCIe link is ready */
eeh_bridge_check_link(edev, dn); eeh_bridge_check_link(edev);
} }
static void eeh_restore_device_bars(struct eeh_dev *edev, static void eeh_restore_device_bars(struct eeh_dev *edev)
struct device_node *dn)
{ {
struct pci_dn *pdn = eeh_dev_to_pdn(edev);
int i; int i;
u32 cmd; u32 cmd;
for (i = 4; i < 10; i++) for (i = 4; i < 10; i++)
eeh_ops->write_config(dn, i*4, 4, edev->config_space[i]); eeh_ops->write_config(pdn, i*4, 4, edev->config_space[i]);
/* 12 == Expansion ROM Address */ /* 12 == Expansion ROM Address */
eeh_ops->write_config(dn, 12*4, 4, edev->config_space[12]); eeh_ops->write_config(pdn, 12*4, 4, edev->config_space[12]);
eeh_ops->write_config(dn, PCI_CACHE_LINE_SIZE, 1, eeh_ops->write_config(pdn, PCI_CACHE_LINE_SIZE, 1,
SAVED_BYTE(PCI_CACHE_LINE_SIZE)); SAVED_BYTE(PCI_CACHE_LINE_SIZE));
eeh_ops->write_config(dn, PCI_LATENCY_TIMER, 1, eeh_ops->write_config(pdn, PCI_LATENCY_TIMER, 1,
SAVED_BYTE(PCI_LATENCY_TIMER)); SAVED_BYTE(PCI_LATENCY_TIMER));
/* max latency, min grant, interrupt pin and line */ /* max latency, min grant, interrupt pin and line */
eeh_ops->write_config(dn, 15*4, 4, edev->config_space[15]); eeh_ops->write_config(pdn, 15*4, 4, edev->config_space[15]);
/* /*
* Restore PERR & SERR bits, some devices require it, * Restore PERR & SERR bits, some devices require it,
* don't touch the other command bits * don't touch the other command bits
*/ */
eeh_ops->read_config(dn, PCI_COMMAND, 4, &cmd); eeh_ops->read_config(pdn, PCI_COMMAND, 4, &cmd);
if (edev->config_space[1] & PCI_COMMAND_PARITY) if (edev->config_space[1] & PCI_COMMAND_PARITY)
cmd |= PCI_COMMAND_PARITY; cmd |= PCI_COMMAND_PARITY;
else else
...@@ -789,7 +804,7 @@ static void eeh_restore_device_bars(struct eeh_dev *edev, ...@@ -789,7 +804,7 @@ static void eeh_restore_device_bars(struct eeh_dev *edev,
cmd |= PCI_COMMAND_SERR; cmd |= PCI_COMMAND_SERR;
else else
cmd &= ~PCI_COMMAND_SERR; cmd &= ~PCI_COMMAND_SERR;
eeh_ops->write_config(dn, PCI_COMMAND, 4, cmd); eeh_ops->write_config(pdn, PCI_COMMAND, 4, cmd);
} }
/** /**
...@@ -804,16 +819,16 @@ static void eeh_restore_device_bars(struct eeh_dev *edev, ...@@ -804,16 +819,16 @@ static void eeh_restore_device_bars(struct eeh_dev *edev,
static void *eeh_restore_one_device_bars(void *data, void *flag) static void *eeh_restore_one_device_bars(void *data, void *flag)
{ {
struct eeh_dev *edev = (struct eeh_dev *)data; struct eeh_dev *edev = (struct eeh_dev *)data;
struct device_node *dn = eeh_dev_to_of_node(edev); struct pci_dn *pdn = eeh_dev_to_pdn(edev);
/* Do special restore for bridges */ /* Do special restore for bridges */
if (edev->mode & EEH_DEV_BRIDGE) if (edev->mode & EEH_DEV_BRIDGE)
eeh_restore_bridge_bars(edev, dn); eeh_restore_bridge_bars(edev);
else else
eeh_restore_device_bars(edev, dn); eeh_restore_device_bars(edev);
if (eeh_ops->restore_config) if (eeh_ops->restore_config && pdn)
eeh_ops->restore_config(dn); eeh_ops->restore_config(pdn);
return NULL; return NULL;
} }
......
...@@ -72,7 +72,7 @@ static int of_pci_phb_probe(struct platform_device *dev) ...@@ -72,7 +72,7 @@ static int of_pci_phb_probe(struct platform_device *dev)
/* Register devices with EEH */ /* Register devices with EEH */
if (dev->dev.of_node->child) if (dev->dev.of_node->child)
eeh_add_device_tree_early(dev->dev.of_node); eeh_add_device_tree_early(PCI_DN(dev->dev.of_node));
/* Scan the bus */ /* Scan the bus */
pcibios_scan_phb(phb); pcibios_scan_phb(phb);
......
...@@ -75,7 +75,7 @@ void pcibios_add_pci_devices(struct pci_bus * bus) ...@@ -75,7 +75,7 @@ void pcibios_add_pci_devices(struct pci_bus * bus)
struct pci_dev *dev; struct pci_dev *dev;
struct device_node *dn = pci_bus_to_OF_node(bus); struct device_node *dn = pci_bus_to_OF_node(bus);
eeh_add_device_tree_early(dn); eeh_add_device_tree_early(PCI_DN(dn));
mode = PCI_PROBE_NORMAL; mode = PCI_PROBE_NORMAL;
if (ppc_md.pci_probe_mode) if (ppc_md.pci_probe_mode)
......
...@@ -32,12 +32,108 @@ ...@@ -32,12 +32,108 @@
#include <asm/ppc-pci.h> #include <asm/ppc-pci.h>
#include <asm/firmware.h> #include <asm/firmware.h>
/*
* The function is used to find the firmware data of one
* specific PCI device, which is attached to the indicated
* PCI bus. For VFs, their firmware data is linked to that
* one of PF's bridge. For other devices, their firmware
* data is linked to that of their bridge.
*/
static struct pci_dn *pci_bus_to_pdn(struct pci_bus *bus)
{
struct pci_bus *pbus;
struct device_node *dn;
struct pci_dn *pdn;
/*
* We probably have virtual bus which doesn't
* have associated bridge.
*/
pbus = bus;
while (pbus) {
if (pci_is_root_bus(pbus) || pbus->self)
break;
pbus = pbus->parent;
}
/*
* Except virtual bus, all PCI buses should
* have device nodes.
*/
dn = pci_bus_to_OF_node(pbus);
pdn = dn ? PCI_DN(dn) : NULL;
return pdn;
}
struct pci_dn *pci_get_pdn_by_devfn(struct pci_bus *bus,
int devfn)
{
struct device_node *dn = NULL;
struct pci_dn *parent, *pdn;
struct pci_dev *pdev = NULL;
/* Fast path: fetch from PCI device */
list_for_each_entry(pdev, &bus->devices, bus_list) {
if (pdev->devfn == devfn) {
if (pdev->dev.archdata.pci_data)
return pdev->dev.archdata.pci_data;
dn = pci_device_to_OF_node(pdev);
break;
}
}
/* Fast path: fetch from device node */
pdn = dn ? PCI_DN(dn) : NULL;
if (pdn)
return pdn;
/* Slow path: fetch from firmware data hierarchy */
parent = pci_bus_to_pdn(bus);
if (!parent)
return NULL;
list_for_each_entry(pdn, &parent->child_list, list) {
if (pdn->busno == bus->number &&
pdn->devfn == devfn)
return pdn;
}
return NULL;
}
struct pci_dn *pci_get_pdn(struct pci_dev *pdev) struct pci_dn *pci_get_pdn(struct pci_dev *pdev)
{ {
struct device_node *dn = pci_device_to_OF_node(pdev); struct device_node *dn;
if (!dn) struct pci_dn *parent, *pdn;
/* Search device directly */
if (pdev->dev.archdata.pci_data)
return pdev->dev.archdata.pci_data;
/* Check device node */
dn = pci_device_to_OF_node(pdev);
pdn = dn ? PCI_DN(dn) : NULL;
if (pdn)
return pdn;
/*
* VFs don't have device nodes. We hook their
* firmware data to PF's bridge.
*/
parent = pci_bus_to_pdn(pdev->bus);
if (!parent)
return NULL;
list_for_each_entry(pdn, &parent->child_list, list) {
if (pdn->busno == pdev->bus->number &&
pdn->devfn == pdev->devfn)
return pdn;
}
return NULL; return NULL;
return PCI_DN(dn);
} }
/* /*
...@@ -49,6 +145,7 @@ void *update_dn_pci_info(struct device_node *dn, void *data) ...@@ -49,6 +145,7 @@ void *update_dn_pci_info(struct device_node *dn, void *data)
struct pci_controller *phb = data; struct pci_controller *phb = data;
const __be32 *type = of_get_property(dn, "ibm,pci-config-space-type", NULL); const __be32 *type = of_get_property(dn, "ibm,pci-config-space-type", NULL);
const __be32 *regs; const __be32 *regs;
struct device_node *parent;
struct pci_dn *pdn; struct pci_dn *pdn;
pdn = zalloc_maybe_bootmem(sizeof(*pdn), GFP_KERNEL); pdn = zalloc_maybe_bootmem(sizeof(*pdn), GFP_KERNEL);
...@@ -69,7 +166,25 @@ void *update_dn_pci_info(struct device_node *dn, void *data) ...@@ -69,7 +166,25 @@ void *update_dn_pci_info(struct device_node *dn, void *data)
pdn->devfn = (addr >> 8) & 0xff; pdn->devfn = (addr >> 8) & 0xff;
} }
/* vendor/device IDs and class code */
regs = of_get_property(dn, "vendor-id", NULL);
pdn->vendor_id = regs ? of_read_number(regs, 1) : 0;
regs = of_get_property(dn, "device-id", NULL);
pdn->device_id = regs ? of_read_number(regs, 1) : 0;
regs = of_get_property(dn, "class-code", NULL);
pdn->class_code = regs ? of_read_number(regs, 1) : 0;
/* Extended config space */
pdn->pci_ext_config_space = (type && of_read_number(type, 1) == 1); pdn->pci_ext_config_space = (type && of_read_number(type, 1) == 1);
/* Attach to parent node */
INIT_LIST_HEAD(&pdn->child_list);
INIT_LIST_HEAD(&pdn->list);
parent = of_get_parent(dn);
pdn->parent = parent ? PCI_DN(parent) : NULL;
if (pdn->parent)
list_add_tail(&pdn->list, &pdn->parent->child_list);
return NULL; return NULL;
} }
...@@ -131,6 +246,46 @@ void *traverse_pci_devices(struct device_node *start, traverse_func pre, ...@@ -131,6 +246,46 @@ void *traverse_pci_devices(struct device_node *start, traverse_func pre,
return NULL; return NULL;
} }
static struct pci_dn *pci_dn_next_one(struct pci_dn *root,
struct pci_dn *pdn)
{
struct list_head *next = pdn->child_list.next;
if (next != &pdn->child_list)
return list_entry(next, struct pci_dn, list);
while (1) {
if (pdn == root)
return NULL;
next = pdn->list.next;
if (next != &pdn->parent->child_list)
break;
pdn = pdn->parent;
}
return list_entry(next, struct pci_dn, list);
}
void *traverse_pci_dn(struct pci_dn *root,
void *(*fn)(struct pci_dn *, void *),
void *data)
{
struct pci_dn *pdn = root;
void *ret;
/* Only scan the child nodes */
for (pdn = pci_dn_next_one(root, pdn); pdn;
pdn = pci_dn_next_one(root, pdn)) {
ret = fn(pdn, data);
if (ret)
return ret;
}
return NULL;
}
/** /**
* pci_devs_phb_init_dynamic - setup pci devices under this PHB * pci_devs_phb_init_dynamic - setup pci devices under this PHB
* phb: pci-to-host bridge (top-level bridge connecting to cpu) * phb: pci-to-host bridge (top-level bridge connecting to cpu)
...@@ -147,8 +302,12 @@ void pci_devs_phb_init_dynamic(struct pci_controller *phb) ...@@ -147,8 +302,12 @@ void pci_devs_phb_init_dynamic(struct pci_controller *phb)
/* PHB nodes themselves must not match */ /* PHB nodes themselves must not match */
update_dn_pci_info(dn, phb); update_dn_pci_info(dn, phb);
pdn = dn->data; pdn = dn->data;
if (pdn) if (pdn) {
pdn->devfn = pdn->busno = -1; pdn->devfn = pdn->busno = -1;
pdn->vendor_id = pdn->device_id = pdn->class_code = 0;
pdn->phb = phb;
phb->pci_data = pdn;
}
/* Update dn->phb ptrs for new phb and children devices */ /* Update dn->phb ptrs for new phb and children devices */
traverse_pci_devices(dn, update_dn_pci_info, phb); traverse_pci_devices(dn, update_dn_pci_info, phb);
...@@ -171,3 +330,16 @@ void __init pci_devs_phb_init(void) ...@@ -171,3 +330,16 @@ void __init pci_devs_phb_init(void)
list_for_each_entry_safe(phb, tmp, &hose_list, list_node) list_for_each_entry_safe(phb, tmp, &hose_list, list_node)
pci_devs_phb_init_dynamic(phb); pci_devs_phb_init_dynamic(phb);
} }
static void pci_dev_pdn_setup(struct pci_dev *pdev)
{
struct pci_dn *pdn;
if (pdev->dev.archdata.pci_data)
return;
/* Setup the fast path */
pdn = pci_get_pdn(pdev);
pdev->dev.archdata.pci_data = pdn;
}
DECLARE_PCI_FIXUP_EARLY(PCI_ANY_ID, PCI_ANY_ID, pci_dev_pdn_setup);
...@@ -305,7 +305,7 @@ static struct pci_dev *of_scan_pci_dev(struct pci_bus *bus, ...@@ -305,7 +305,7 @@ static struct pci_dev *of_scan_pci_dev(struct pci_bus *bus,
const __be32 *reg; const __be32 *reg;
int reglen, devfn; int reglen, devfn;
#ifdef CONFIG_EEH #ifdef CONFIG_EEH
struct eeh_dev *edev = of_node_to_eeh_dev(dn); struct eeh_dev *edev = pdn_to_eeh_dev(PCI_DN(dn));
#endif #endif
pr_debug(" * %s\n", dn->full_name); pr_debug(" * %s\n", dn->full_name);
......
...@@ -113,7 +113,7 @@ static int rtas_pci_read_config(struct pci_bus *bus, ...@@ -113,7 +113,7 @@ static int rtas_pci_read_config(struct pci_bus *bus,
ret = rtas_read_config(pdn, where, size, val); ret = rtas_read_config(pdn, where, size, val);
if (*val == EEH_IO_ERROR_VALUE(size) && if (*val == EEH_IO_ERROR_VALUE(size) &&
eeh_dev_check_failure(of_node_to_eeh_dev(dn))) eeh_dev_check_failure(pdn_to_eeh_dev(pdn)))
return PCIBIOS_DEVICE_NOT_FOUND; return PCIBIOS_DEVICE_NOT_FOUND;
return ret; return ret;
......
...@@ -5,7 +5,7 @@ obj-y += opal-msglog.o opal-hmi.o opal-power.o ...@@ -5,7 +5,7 @@ obj-y += opal-msglog.o opal-hmi.o opal-power.o
obj-$(CONFIG_SMP) += smp.o subcore.o subcore-asm.o obj-$(CONFIG_SMP) += smp.o subcore.o subcore-asm.o
obj-$(CONFIG_PCI) += pci.o pci-p5ioc2.o pci-ioda.o obj-$(CONFIG_PCI) += pci.o pci-p5ioc2.o pci-ioda.o
obj-$(CONFIG_EEH) += eeh-ioda.o eeh-powernv.o obj-$(CONFIG_EEH) += eeh-powernv.o
obj-$(CONFIG_PPC_SCOM) += opal-xscom.o obj-$(CONFIG_PPC_SCOM) += opal-xscom.o
obj-$(CONFIG_MEMORY_FAILURE) += opal-memory-errors.o obj-$(CONFIG_MEMORY_FAILURE) += opal-memory-errors.o
obj-$(CONFIG_TRACEPOINTS) += opal-tracepoints.o obj-$(CONFIG_TRACEPOINTS) += opal-tracepoints.o
This diff is collapsed.
...@@ -1777,7 +1777,8 @@ static void pnv_ioda_setup_pe_seg(struct pci_controller *hose, ...@@ -1777,7 +1777,8 @@ static void pnv_ioda_setup_pe_seg(struct pci_controller *hose,
region.start += phb->ioda.io_segsize; region.start += phb->ioda.io_segsize;
index++; index++;
} }
} else if (res->flags & IORESOURCE_MEM) { } else if ((res->flags & IORESOURCE_MEM) &&
!pnv_pci_is_mem_pref_64(res->flags)) {
region.start = res->start - region.start = res->start -
hose->mem_offset[0] - hose->mem_offset[0] -
phb->ioda.m32_pci_base; phb->ioda.m32_pci_base;
...@@ -2078,9 +2079,6 @@ static void __init pnv_pci_init_ioda_phb(struct device_node *np, ...@@ -2078,9 +2079,6 @@ static void __init pnv_pci_init_ioda_phb(struct device_node *np,
phb->get_pe_state = pnv_ioda_get_pe_state; phb->get_pe_state = pnv_ioda_get_pe_state;
phb->freeze_pe = pnv_ioda_freeze_pe; phb->freeze_pe = pnv_ioda_freeze_pe;
phb->unfreeze_pe = pnv_ioda_unfreeze_pe; phb->unfreeze_pe = pnv_ioda_unfreeze_pe;
#ifdef CONFIG_EEH
phb->eeh_ops = &ioda_eeh_ops;
#endif
/* Setup RID -> PE mapping function */ /* Setup RID -> PE mapping function */
phb->bdfn_to_pe = pnv_ioda_bdfn_to_pe; phb->bdfn_to_pe = pnv_ioda_bdfn_to_pe;
...@@ -2121,8 +2119,8 @@ static void __init pnv_pci_init_ioda_phb(struct device_node *np, ...@@ -2121,8 +2119,8 @@ static void __init pnv_pci_init_ioda_phb(struct device_node *np,
*/ */
if (is_kdump_kernel()) { if (is_kdump_kernel()) {
pr_info(" Issue PHB reset ...\n"); pr_info(" Issue PHB reset ...\n");
ioda_eeh_phb_reset(hose, EEH_RESET_FUNDAMENTAL); pnv_eeh_phb_reset(hose, EEH_RESET_FUNDAMENTAL);
ioda_eeh_phb_reset(hose, EEH_RESET_DEACTIVATE); pnv_eeh_phb_reset(hose, EEH_RESET_DEACTIVATE);
} }
/* Remove M64 resource if we can't configure it successfully */ /* Remove M64 resource if we can't configure it successfully */
......
...@@ -366,9 +366,9 @@ static void pnv_pci_handle_eeh_config(struct pnv_phb *phb, u32 pe_no) ...@@ -366,9 +366,9 @@ static void pnv_pci_handle_eeh_config(struct pnv_phb *phb, u32 pe_no)
spin_unlock_irqrestore(&phb->lock, flags); spin_unlock_irqrestore(&phb->lock, flags);
} }
static void pnv_pci_config_check_eeh(struct pnv_phb *phb, static void pnv_pci_config_check_eeh(struct pci_dn *pdn)
struct device_node *dn)
{ {
struct pnv_phb *phb = pdn->phb->private_data;
u8 fstate; u8 fstate;
__be16 pcierr; __be16 pcierr;
int pe_no; int pe_no;
...@@ -379,7 +379,7 @@ static void pnv_pci_config_check_eeh(struct pnv_phb *phb, ...@@ -379,7 +379,7 @@ static void pnv_pci_config_check_eeh(struct pnv_phb *phb,
* setup that yet. So all ER errors should be mapped to * setup that yet. So all ER errors should be mapped to
* reserved PE. * reserved PE.
*/ */
pe_no = PCI_DN(dn)->pe_number; pe_no = pdn->pe_number;
if (pe_no == IODA_INVALID_PE) { if (pe_no == IODA_INVALID_PE) {
if (phb->type == PNV_PHB_P5IOC2) if (phb->type == PNV_PHB_P5IOC2)
pe_no = 0; pe_no = 0;
...@@ -407,8 +407,7 @@ static void pnv_pci_config_check_eeh(struct pnv_phb *phb, ...@@ -407,8 +407,7 @@ static void pnv_pci_config_check_eeh(struct pnv_phb *phb,
} }
cfg_dbg(" -> EEH check, bdfn=%04x PE#%d fstate=%x\n", cfg_dbg(" -> EEH check, bdfn=%04x PE#%d fstate=%x\n",
(PCI_DN(dn)->busno << 8) | (PCI_DN(dn)->devfn), (pdn->busno << 8) | (pdn->devfn), pe_no, fstate);
pe_no, fstate);
/* Clear the frozen state if applicable */ /* Clear the frozen state if applicable */
if (fstate == OPAL_EEH_STOPPED_MMIO_FREEZE || if (fstate == OPAL_EEH_STOPPED_MMIO_FREEZE ||
...@@ -425,10 +424,9 @@ static void pnv_pci_config_check_eeh(struct pnv_phb *phb, ...@@ -425,10 +424,9 @@ static void pnv_pci_config_check_eeh(struct pnv_phb *phb,
} }
} }
int pnv_pci_cfg_read(struct device_node *dn, int pnv_pci_cfg_read(struct pci_dn *pdn,
int where, int size, u32 *val) int where, int size, u32 *val)
{ {
struct pci_dn *pdn = PCI_DN(dn);
struct pnv_phb *phb = pdn->phb->private_data; struct pnv_phb *phb = pdn->phb->private_data;
u32 bdfn = (pdn->busno << 8) | pdn->devfn; u32 bdfn = (pdn->busno << 8) | pdn->devfn;
s64 rc; s64 rc;
...@@ -462,10 +460,9 @@ int pnv_pci_cfg_read(struct device_node *dn, ...@@ -462,10 +460,9 @@ int pnv_pci_cfg_read(struct device_node *dn,
return PCIBIOS_SUCCESSFUL; return PCIBIOS_SUCCESSFUL;
} }
int pnv_pci_cfg_write(struct device_node *dn, int pnv_pci_cfg_write(struct pci_dn *pdn,
int where, int size, u32 val) int where, int size, u32 val)
{ {
struct pci_dn *pdn = PCI_DN(dn);
struct pnv_phb *phb = pdn->phb->private_data; struct pnv_phb *phb = pdn->phb->private_data;
u32 bdfn = (pdn->busno << 8) | pdn->devfn; u32 bdfn = (pdn->busno << 8) | pdn->devfn;
...@@ -489,18 +486,17 @@ int pnv_pci_cfg_write(struct device_node *dn, ...@@ -489,18 +486,17 @@ int pnv_pci_cfg_write(struct device_node *dn,
} }
#if CONFIG_EEH #if CONFIG_EEH
static bool pnv_pci_cfg_check(struct pci_controller *hose, static bool pnv_pci_cfg_check(struct pci_dn *pdn)
struct device_node *dn)
{ {
struct eeh_dev *edev = NULL; struct eeh_dev *edev = NULL;
struct pnv_phb *phb = hose->private_data; struct pnv_phb *phb = pdn->phb->private_data;
/* EEH not enabled ? */ /* EEH not enabled ? */
if (!(phb->flags & PNV_PHB_FLAG_EEH)) if (!(phb->flags & PNV_PHB_FLAG_EEH))
return true; return true;
/* PE reset or device removed ? */ /* PE reset or device removed ? */
edev = of_node_to_eeh_dev(dn); edev = pdn->edev;
if (edev) { if (edev) {
if (edev->pe && if (edev->pe &&
(edev->pe->state & EEH_PE_CFG_BLOCKED)) (edev->pe->state & EEH_PE_CFG_BLOCKED))
...@@ -513,8 +509,7 @@ static bool pnv_pci_cfg_check(struct pci_controller *hose, ...@@ -513,8 +509,7 @@ static bool pnv_pci_cfg_check(struct pci_controller *hose,
return true; return true;
} }
#else #else
static inline pnv_pci_cfg_check(struct pci_controller *hose, static inline pnv_pci_cfg_check(struct pci_dn *pdn)
struct device_node *dn)
{ {
return true; return true;
} }
...@@ -524,32 +519,26 @@ static int pnv_pci_read_config(struct pci_bus *bus, ...@@ -524,32 +519,26 @@ static int pnv_pci_read_config(struct pci_bus *bus,
unsigned int devfn, unsigned int devfn,
int where, int size, u32 *val) int where, int size, u32 *val)
{ {
struct device_node *dn, *busdn = pci_bus_to_OF_node(bus);
struct pci_dn *pdn; struct pci_dn *pdn;
struct pnv_phb *phb; struct pnv_phb *phb;
bool found = false;
int ret; int ret;
*val = 0xFFFFFFFF; *val = 0xFFFFFFFF;
for (dn = busdn->child; dn; dn = dn->sibling) { pdn = pci_get_pdn_by_devfn(bus, devfn);
pdn = PCI_DN(dn); if (!pdn)
if (pdn && pdn->devfn == devfn) { return PCIBIOS_DEVICE_NOT_FOUND;
phb = pdn->phb->private_data;
found = true;
break;
}
}
if (!found || !pnv_pci_cfg_check(pdn->phb, dn)) if (!pnv_pci_cfg_check(pdn))
return PCIBIOS_DEVICE_NOT_FOUND; return PCIBIOS_DEVICE_NOT_FOUND;
ret = pnv_pci_cfg_read(dn, where, size, val); ret = pnv_pci_cfg_read(pdn, where, size, val);
if (phb->flags & PNV_PHB_FLAG_EEH) { phb = pdn->phb->private_data;
if (phb->flags & PNV_PHB_FLAG_EEH && pdn->edev) {
if (*val == EEH_IO_ERROR_VALUE(size) && if (*val == EEH_IO_ERROR_VALUE(size) &&
eeh_dev_check_failure(of_node_to_eeh_dev(dn))) eeh_dev_check_failure(pdn->edev))
return PCIBIOS_DEVICE_NOT_FOUND; return PCIBIOS_DEVICE_NOT_FOUND;
} else { } else {
pnv_pci_config_check_eeh(phb, dn); pnv_pci_config_check_eeh(pdn);
} }
return ret; return ret;
...@@ -559,27 +548,21 @@ static int pnv_pci_write_config(struct pci_bus *bus, ...@@ -559,27 +548,21 @@ static int pnv_pci_write_config(struct pci_bus *bus,
unsigned int devfn, unsigned int devfn,
int where, int size, u32 val) int where, int size, u32 val)
{ {
struct device_node *dn, *busdn = pci_bus_to_OF_node(bus);
struct pci_dn *pdn; struct pci_dn *pdn;
struct pnv_phb *phb; struct pnv_phb *phb;
bool found = false;
int ret; int ret;
for (dn = busdn->child; dn; dn = dn->sibling) { pdn = pci_get_pdn_by_devfn(bus, devfn);
pdn = PCI_DN(dn); if (!pdn)
if (pdn && pdn->devfn == devfn) { return PCIBIOS_DEVICE_NOT_FOUND;
phb = pdn->phb->private_data;
found = true;
break;
}
}
if (!found || !pnv_pci_cfg_check(pdn->phb, dn)) if (!pnv_pci_cfg_check(pdn))
return PCIBIOS_DEVICE_NOT_FOUND; return PCIBIOS_DEVICE_NOT_FOUND;
ret = pnv_pci_cfg_write(dn, where, size, val); ret = pnv_pci_cfg_write(pdn, where, size, val);
phb = pdn->phb->private_data;
if (!(phb->flags & PNV_PHB_FLAG_EEH)) if (!(phb->flags & PNV_PHB_FLAG_EEH))
pnv_pci_config_check_eeh(phb, dn); pnv_pci_config_check_eeh(pdn);
return ret; return ret;
} }
......
...@@ -75,22 +75,6 @@ struct pnv_ioda_pe { ...@@ -75,22 +75,6 @@ struct pnv_ioda_pe {
struct list_head list; struct list_head list;
}; };
/* IOC dependent EEH operations */
#ifdef CONFIG_EEH
struct pnv_eeh_ops {
int (*post_init)(struct pci_controller *hose);
int (*set_option)(struct eeh_pe *pe, int option);
int (*get_state)(struct eeh_pe *pe);
int (*reset)(struct eeh_pe *pe, int option);
int (*get_log)(struct eeh_pe *pe, int severity,
char *drv_log, unsigned long len);
int (*configure_bridge)(struct eeh_pe *pe);
int (*err_inject)(struct eeh_pe *pe, int type, int func,
unsigned long addr, unsigned long mask);
int (*next_error)(struct eeh_pe **pe);
};
#endif /* CONFIG_EEH */
#define PNV_PHB_FLAG_EEH (1 << 0) #define PNV_PHB_FLAG_EEH (1 << 0)
struct pnv_phb { struct pnv_phb {
...@@ -104,10 +88,6 @@ struct pnv_phb { ...@@ -104,10 +88,6 @@ struct pnv_phb {
int initialized; int initialized;
spinlock_t lock; spinlock_t lock;
#ifdef CONFIG_EEH
struct pnv_eeh_ops *eeh_ops;
#endif
#ifdef CONFIG_DEBUG_FS #ifdef CONFIG_DEBUG_FS
int has_dbgfs; int has_dbgfs;
struct dentry *dbgfs; struct dentry *dbgfs;
...@@ -213,15 +193,12 @@ struct pnv_phb { ...@@ -213,15 +193,12 @@ struct pnv_phb {
}; };
extern struct pci_ops pnv_pci_ops; extern struct pci_ops pnv_pci_ops;
#ifdef CONFIG_EEH
extern struct pnv_eeh_ops ioda_eeh_ops;
#endif
void pnv_pci_dump_phb_diag_data(struct pci_controller *hose, void pnv_pci_dump_phb_diag_data(struct pci_controller *hose,
unsigned char *log_buff); unsigned char *log_buff);
int pnv_pci_cfg_read(struct device_node *dn, int pnv_pci_cfg_read(struct pci_dn *pdn,
int where, int size, u32 *val); int where, int size, u32 *val);
int pnv_pci_cfg_write(struct device_node *dn, int pnv_pci_cfg_write(struct pci_dn *pdn,
int where, int size, u32 val); int where, int size, u32 val);
extern void pnv_pci_setup_iommu_table(struct iommu_table *tbl, extern void pnv_pci_setup_iommu_table(struct iommu_table *tbl,
void *tce_mem, u64 tce_size, void *tce_mem, u64 tce_size,
...@@ -232,6 +209,6 @@ extern void pnv_pci_init_ioda2_phb(struct device_node *np); ...@@ -232,6 +209,6 @@ extern void pnv_pci_init_ioda2_phb(struct device_node *np);
extern void pnv_pci_ioda_tce_invalidate(struct iommu_table *tbl, extern void pnv_pci_ioda_tce_invalidate(struct iommu_table *tbl,
__be64 *startp, __be64 *endp, bool rm); __be64 *startp, __be64 *endp, bool rm);
extern void pnv_pci_reset_secondary_bus(struct pci_dev *dev); extern void pnv_pci_reset_secondary_bus(struct pci_dev *dev);
extern int ioda_eeh_phb_reset(struct pci_controller *hose, int option); extern int pnv_eeh_phb_reset(struct pci_controller *hose, int option);
#endif /* __POWERNV_PCI_H */ #endif /* __POWERNV_PCI_H */
...@@ -118,9 +118,8 @@ static int pseries_eeh_init(void) ...@@ -118,9 +118,8 @@ static int pseries_eeh_init(void)
return 0; return 0;
} }
static int pseries_eeh_cap_start(struct device_node *dn) static int pseries_eeh_cap_start(struct pci_dn *pdn)
{ {
struct pci_dn *pdn = PCI_DN(dn);
u32 status; u32 status;
if (!pdn) if (!pdn)
...@@ -134,10 +133,9 @@ static int pseries_eeh_cap_start(struct device_node *dn) ...@@ -134,10 +133,9 @@ static int pseries_eeh_cap_start(struct device_node *dn)
} }
static int pseries_eeh_find_cap(struct device_node *dn, int cap) static int pseries_eeh_find_cap(struct pci_dn *pdn, int cap)
{ {
struct pci_dn *pdn = PCI_DN(dn); int pos = pseries_eeh_cap_start(pdn);
int pos = pseries_eeh_cap_start(dn);
int cnt = 48; /* Maximal number of capabilities */ int cnt = 48; /* Maximal number of capabilities */
u32 id; u32 id;
...@@ -160,10 +158,9 @@ static int pseries_eeh_find_cap(struct device_node *dn, int cap) ...@@ -160,10 +158,9 @@ static int pseries_eeh_find_cap(struct device_node *dn, int cap)
return 0; return 0;
} }
static int pseries_eeh_find_ecap(struct device_node *dn, int cap) static int pseries_eeh_find_ecap(struct pci_dn *pdn, int cap)
{ {
struct pci_dn *pdn = PCI_DN(dn); struct eeh_dev *edev = pdn_to_eeh_dev(pdn);
struct eeh_dev *edev = of_node_to_eeh_dev(dn);
u32 header; u32 header;
int pos = 256; int pos = 256;
int ttl = (4096 - 256) / 8; int ttl = (4096 - 256) / 8;
...@@ -191,53 +188,44 @@ static int pseries_eeh_find_ecap(struct device_node *dn, int cap) ...@@ -191,53 +188,44 @@ static int pseries_eeh_find_ecap(struct device_node *dn, int cap)
} }
/** /**
* pseries_eeh_of_probe - EEH probe on the given device * pseries_eeh_probe - EEH probe on the given device
* @dn: OF node * @pdn: PCI device node
* @flag: Unused * @data: Unused
* *
* When EEH module is installed during system boot, all PCI devices * When EEH module is installed during system boot, all PCI devices
* are checked one by one to see if it supports EEH. The function * are checked one by one to see if it supports EEH. The function
* is introduced for the purpose. * is introduced for the purpose.
*/ */
static void *pseries_eeh_of_probe(struct device_node *dn, void *flag) static void *pseries_eeh_probe(struct pci_dn *pdn, void *data)
{ {
struct eeh_dev *edev; struct eeh_dev *edev;
struct eeh_pe pe; struct eeh_pe pe;
struct pci_dn *pdn = PCI_DN(dn);
const __be32 *classp, *vendorp, *devicep;
u32 class_code;
const __be32 *regs;
u32 pcie_flags; u32 pcie_flags;
int enable = 0; int enable = 0;
int ret; int ret;
/* Retrieve OF node and eeh device */ /* Retrieve OF node and eeh device */
edev = of_node_to_eeh_dev(dn); edev = pdn_to_eeh_dev(pdn);
if (edev->pe || !of_device_is_available(dn)) if (!edev || edev->pe)
return NULL; return NULL;
/* Retrieve class/vendor/device IDs */ /* Check class/vendor/device IDs */
classp = of_get_property(dn, "class-code", NULL); if (!pdn->vendor_id || !pdn->device_id || !pdn->class_code)
vendorp = of_get_property(dn, "vendor-id", NULL);
devicep = of_get_property(dn, "device-id", NULL);
/* Skip for bad OF node or PCI-ISA bridge */
if (!classp || !vendorp || !devicep)
return NULL;
if (dn->type && !strcmp(dn->type, "isa"))
return NULL; return NULL;
class_code = of_read_number(classp, 1); /* Skip for PCI-ISA bridge */
if ((pdn->class_code >> 8) == PCI_CLASS_BRIDGE_ISA)
return NULL;
/* /*
* Update class code and mode of eeh device. We need * Update class code and mode of eeh device. We need
* correctly reflects that current device is root port * correctly reflects that current device is root port
* or PCIe switch downstream port. * or PCIe switch downstream port.
*/ */
edev->class_code = class_code; edev->class_code = pdn->class_code;
edev->pcix_cap = pseries_eeh_find_cap(dn, PCI_CAP_ID_PCIX); edev->pcix_cap = pseries_eeh_find_cap(pdn, PCI_CAP_ID_PCIX);
edev->pcie_cap = pseries_eeh_find_cap(dn, PCI_CAP_ID_EXP); edev->pcie_cap = pseries_eeh_find_cap(pdn, PCI_CAP_ID_EXP);
edev->aer_cap = pseries_eeh_find_ecap(dn, PCI_EXT_CAP_ID_ERR); edev->aer_cap = pseries_eeh_find_ecap(pdn, PCI_EXT_CAP_ID_ERR);
edev->mode &= 0xFFFFFF00; edev->mode &= 0xFFFFFF00;
if ((edev->class_code >> 8) == PCI_CLASS_BRIDGE_PCI) { if ((edev->class_code >> 8) == PCI_CLASS_BRIDGE_PCI) {
edev->mode |= EEH_DEV_BRIDGE; edev->mode |= EEH_DEV_BRIDGE;
...@@ -252,24 +240,16 @@ static void *pseries_eeh_of_probe(struct device_node *dn, void *flag) ...@@ -252,24 +240,16 @@ static void *pseries_eeh_of_probe(struct device_node *dn, void *flag)
} }
} }
/* Retrieve the device address */
regs = of_get_property(dn, "reg", NULL);
if (!regs) {
pr_warn("%s: OF node property %s::reg not found\n",
__func__, dn->full_name);
return NULL;
}
/* Initialize the fake PE */ /* Initialize the fake PE */
memset(&pe, 0, sizeof(struct eeh_pe)); memset(&pe, 0, sizeof(struct eeh_pe));
pe.phb = edev->phb; pe.phb = edev->phb;
pe.config_addr = of_read_number(regs, 1); pe.config_addr = (pdn->busno << 16) | (pdn->devfn << 8);
/* Enable EEH on the device */ /* Enable EEH on the device */
ret = eeh_ops->set_option(&pe, EEH_OPT_ENABLE); ret = eeh_ops->set_option(&pe, EEH_OPT_ENABLE);
if (!ret) { if (!ret) {
edev->config_addr = of_read_number(regs, 1);
/* Retrieve PE address */ /* Retrieve PE address */
edev->config_addr = (pdn->busno << 16) | (pdn->devfn << 8);
edev->pe_config_addr = eeh_ops->get_pe_addr(&pe); edev->pe_config_addr = eeh_ops->get_pe_addr(&pe);
pe.addr = edev->pe_config_addr; pe.addr = edev->pe_config_addr;
...@@ -285,16 +265,17 @@ static void *pseries_eeh_of_probe(struct device_node *dn, void *flag) ...@@ -285,16 +265,17 @@ static void *pseries_eeh_of_probe(struct device_node *dn, void *flag)
eeh_add_flag(EEH_ENABLED); eeh_add_flag(EEH_ENABLED);
eeh_add_to_parent_pe(edev); eeh_add_to_parent_pe(edev);
pr_debug("%s: EEH enabled on %s PHB#%d-PE#%x, config addr#%x\n", pr_debug("%s: EEH enabled on %02x:%02x.%01x PHB#%d-PE#%x\n",
__func__, dn->full_name, pe.phb->global_number, __func__, pdn->busno, PCI_SLOT(pdn->devfn),
pe.addr, pe.config_addr); PCI_FUNC(pdn->devfn), pe.phb->global_number,
} else if (dn->parent && of_node_to_eeh_dev(dn->parent) && pe.addr);
(of_node_to_eeh_dev(dn->parent))->pe) { } else if (pdn->parent && pdn_to_eeh_dev(pdn->parent) &&
(pdn_to_eeh_dev(pdn->parent))->pe) {
/* This device doesn't support EEH, but it may have an /* This device doesn't support EEH, but it may have an
* EEH parent, in which case we mark it as supported. * EEH parent, in which case we mark it as supported.
*/ */
edev->config_addr = of_node_to_eeh_dev(dn->parent)->config_addr; edev->config_addr = pdn_to_eeh_dev(pdn->parent)->config_addr;
edev->pe_config_addr = of_node_to_eeh_dev(dn->parent)->pe_config_addr; edev->pe_config_addr = pdn_to_eeh_dev(pdn->parent)->pe_config_addr;
eeh_add_to_parent_pe(edev); eeh_add_to_parent_pe(edev);
} }
} }
...@@ -670,45 +651,36 @@ static int pseries_eeh_configure_bridge(struct eeh_pe *pe) ...@@ -670,45 +651,36 @@ static int pseries_eeh_configure_bridge(struct eeh_pe *pe)
/** /**
* pseries_eeh_read_config - Read PCI config space * pseries_eeh_read_config - Read PCI config space
* @dn: device node * @pdn: PCI device node
* @where: PCI address * @where: PCI address
* @size: size to read * @size: size to read
* @val: return value * @val: return value
* *
* Read config space from the speicifed device * Read config space from the speicifed device
*/ */
static int pseries_eeh_read_config(struct device_node *dn, int where, int size, u32 *val) static int pseries_eeh_read_config(struct pci_dn *pdn, int where, int size, u32 *val)
{ {
struct pci_dn *pdn;
pdn = PCI_DN(dn);
return rtas_read_config(pdn, where, size, val); return rtas_read_config(pdn, where, size, val);
} }
/** /**
* pseries_eeh_write_config - Write PCI config space * pseries_eeh_write_config - Write PCI config space
* @dn: device node * @pdn: PCI device node
* @where: PCI address * @where: PCI address
* @size: size to write * @size: size to write
* @val: value to be written * @val: value to be written
* *
* Write config space to the specified device * Write config space to the specified device
*/ */
static int pseries_eeh_write_config(struct device_node *dn, int where, int size, u32 val) static int pseries_eeh_write_config(struct pci_dn *pdn, int where, int size, u32 val)
{ {
struct pci_dn *pdn;
pdn = PCI_DN(dn);
return rtas_write_config(pdn, where, size, val); return rtas_write_config(pdn, where, size, val);
} }
static struct eeh_ops pseries_eeh_ops = { static struct eeh_ops pseries_eeh_ops = {
.name = "pseries", .name = "pseries",
.init = pseries_eeh_init, .init = pseries_eeh_init,
.of_probe = pseries_eeh_of_probe, .probe = pseries_eeh_probe,
.dev_probe = NULL,
.set_option = pseries_eeh_set_option, .set_option = pseries_eeh_set_option,
.get_pe_addr = pseries_eeh_get_pe_addr, .get_pe_addr = pseries_eeh_get_pe_addr,
.get_state = pseries_eeh_get_state, .get_state = pseries_eeh_get_state,
......
...@@ -195,6 +195,7 @@ static struct device_node *find_pe_total_msi(struct pci_dev *dev, int *total) ...@@ -195,6 +195,7 @@ static struct device_node *find_pe_total_msi(struct pci_dev *dev, int *total)
static struct device_node *find_pe_dn(struct pci_dev *dev, int *total) static struct device_node *find_pe_dn(struct pci_dev *dev, int *total)
{ {
struct device_node *dn; struct device_node *dn;
struct pci_dn *pdn;
struct eeh_dev *edev; struct eeh_dev *edev;
/* Found our PE and assume 8 at that point. */ /* Found our PE and assume 8 at that point. */
...@@ -204,10 +205,11 @@ static struct device_node *find_pe_dn(struct pci_dev *dev, int *total) ...@@ -204,10 +205,11 @@ static struct device_node *find_pe_dn(struct pci_dev *dev, int *total)
return NULL; return NULL;
/* Get the top level device in the PE */ /* Get the top level device in the PE */
edev = of_node_to_eeh_dev(dn); edev = pdn_to_eeh_dev(PCI_DN(dn));
if (edev->pe) if (edev->pe)
edev = list_first_entry(&edev->pe->edevs, struct eeh_dev, list); edev = list_first_entry(&edev->pe->edevs, struct eeh_dev, list);
dn = eeh_dev_to_of_node(edev); pdn = eeh_dev_to_pdn(edev);
dn = pdn ? pdn->node : NULL;
if (!dn) if (!dn)
return NULL; return NULL;
......
...@@ -82,7 +82,7 @@ struct pci_controller *init_phb_dynamic(struct device_node *dn) ...@@ -82,7 +82,7 @@ struct pci_controller *init_phb_dynamic(struct device_node *dn)
eeh_dev_phb_init_dynamic(phb); eeh_dev_phb_init_dynamic(phb);
if (dn->child) if (dn->child)
eeh_add_device_tree_early(dn); eeh_add_device_tree_early(PCI_DN(dn));
pcibios_scan_phb(phb); pcibios_scan_phb(phb);
pcibios_finish_adding_to_bus(phb->bus); pcibios_finish_adding_to_bus(phb->bus);
......
...@@ -265,7 +265,7 @@ static int pci_dn_reconfig_notifier(struct notifier_block *nb, unsigned long act ...@@ -265,7 +265,7 @@ static int pci_dn_reconfig_notifier(struct notifier_block *nb, unsigned long act
update_dn_pci_info(np, pci->phb); update_dn_pci_info(np, pci->phb);
/* Create EEH device for the OF node */ /* Create EEH device for the OF node */
eeh_dev_init(np, pci->phb); eeh_dev_init(PCI_DN(np), pci->phb);
} }
break; break;
default: default:
......
...@@ -2523,9 +2523,7 @@ int efx_try_recovery(struct efx_nic *efx) ...@@ -2523,9 +2523,7 @@ int efx_try_recovery(struct efx_nic *efx)
* schedule a 'recover or reset', leading to this recovery handler. * schedule a 'recover or reset', leading to this recovery handler.
* Manually call the eeh failure check function. * Manually call the eeh failure check function.
*/ */
struct eeh_dev *eehdev = struct eeh_dev *eehdev = pci_dev_to_eeh_dev(efx->pci_dev);
of_node_to_eeh_dev(pci_device_to_OF_node(efx->pci_dev));
if (eeh_dev_check_failure(eehdev)) { if (eeh_dev_check_failure(eehdev)) {
/* The EEH mechanisms will handle the error and reset the /* The EEH mechanisms will handle the error and reset the
* device if necessary. * device if necessary.
......
...@@ -205,8 +205,7 @@ static int siena_map_reset_flags(u32 *flags) ...@@ -205,8 +205,7 @@ static int siena_map_reset_flags(u32 *flags)
*/ */
static void siena_monitor(struct efx_nic *efx) static void siena_monitor(struct efx_nic *efx)
{ {
struct eeh_dev *eehdev = struct eeh_dev *eehdev = pci_dev_to_eeh_dev(efx->pci_dev);
of_node_to_eeh_dev(pci_device_to_OF_node(efx->pci_dev));
eeh_dev_check_failure(eehdev); eeh_dev_check_failure(eehdev);
} }
......
...@@ -146,7 +146,7 @@ static void dlpar_pci_add_bus(struct device_node *dn) ...@@ -146,7 +146,7 @@ static void dlpar_pci_add_bus(struct device_node *dn)
struct pci_controller *phb = pdn->phb; struct pci_controller *phb = pdn->phb;
struct pci_dev *dev = NULL; struct pci_dev *dev = NULL;
eeh_add_device_tree_early(dn); eeh_add_device_tree_early(pdn);
/* Add EADS device to PHB bus, adding new entry to bus->devices */ /* Add EADS device to PHB bus, adding new entry to bus->devices */
dev = of_create_pci_dev(dn, phb->bus, pdn->devfn); dev = of_create_pci_dev(dn, phb->bus, pdn->devfn);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment