powerpc/eeh: Remove device_node dependency
The patch removes struct eeh_dev::dn and the corresponding helper functions: eeh_dev_to_of_node() and of_node_to_eeh_dev(). Instead, eeh_dev_to_pdn() and pdn_to_eeh_dev() should be used to get the pdn, which might contain device_node on PowerNV platform. Signed-off-by: Gavin Shan <gwshan@linux.vnet.ibm.com> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
This commit is contained in:
parent
0bd785873c
commit
c6406d8fbb
9 changed files with 55 additions and 81 deletions
|
@ -29,7 +29,6 @@
|
||||||
|
|
||||||
struct pci_dev;
|
struct pci_dev;
|
||||||
struct pci_bus;
|
struct pci_bus;
|
||||||
struct device_node;
|
|
||||||
struct pci_dn;
|
struct pci_dn;
|
||||||
|
|
||||||
#ifdef CONFIG_EEH
|
#ifdef CONFIG_EEH
|
||||||
|
@ -137,17 +136,11 @@ 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_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)
|
|
||||||
{
|
|
||||||
return edev ? edev->dn : NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline struct pci_dn *eeh_dev_to_pdn(struct eeh_dev *edev)
|
static inline struct pci_dn *eeh_dev_to_pdn(struct eeh_dev *edev)
|
||||||
{
|
{
|
||||||
return edev ? edev->pdn : NULL;
|
return edev ? edev->pdn : NULL;
|
||||||
|
|
|
@ -201,25 +201,11 @@ 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)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline struct eeh_dev *pdn_to_eeh_dev(struct pci_dn *pdn)
|
static inline struct eeh_dev *pdn_to_eeh_dev(struct pci_dn *pdn)
|
||||||
{
|
{
|
||||||
return pdn ? pdn->edev : NULL;
|
return pdn ? pdn->edev : NULL;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
#define of_node_to_eeh_dev(x) (NULL)
|
|
||||||
#define pdn_to_eeh_dev(x) (NULL)
|
#define pdn_to_eeh_dev(x) (NULL)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -418,11 +418,11 @@ int eeh_dev_check_failure(struct eeh_dev *edev)
|
||||||
int ret;
|
int ret;
|
||||||
int active_flags = (EEH_STATE_MMIO_ACTIVE | EEH_STATE_DMA_ACTIVE);
|
int active_flags = (EEH_STATE_MMIO_ACTIVE | EEH_STATE_DMA_ACTIVE);
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
struct device_node *dn;
|
struct pci_dn *pdn;
|
||||||
struct pci_dev *dev;
|
struct pci_dev *dev;
|
||||||
struct eeh_pe *pe, *parent_pe, *phb_pe;
|
struct eeh_pe *pe, *parent_pe, *phb_pe;
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
const char *location;
|
const char *location = NULL;
|
||||||
|
|
||||||
eeh_stats.total_mmio_ffs++;
|
eeh_stats.total_mmio_ffs++;
|
||||||
|
|
||||||
|
@ -433,15 +433,14 @@ int eeh_dev_check_failure(struct eeh_dev *edev)
|
||||||
eeh_stats.no_dn++;
|
eeh_stats.no_dn++;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
dn = eeh_dev_to_of_node(edev);
|
|
||||||
dev = eeh_dev_to_pci_dev(edev);
|
dev = eeh_dev_to_pci_dev(edev);
|
||||||
pe = eeh_dev_to_pe(edev);
|
pe = eeh_dev_to_pe(edev);
|
||||||
|
|
||||||
/* Access to IO BARs might get this far and still not want checking. */
|
/* Access to IO BARs might get this far and still not want checking. */
|
||||||
if (!pe) {
|
if (!pe) {
|
||||||
eeh_stats.ignored_check++;
|
eeh_stats.ignored_check++;
|
||||||
pr_debug("EEH: Ignored check for %s %s\n",
|
pr_debug("EEH: Ignored check for %s\n",
|
||||||
eeh_pci_name(dev), dn->full_name);
|
eeh_pci_name(dev));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -477,10 +476,13 @@ int eeh_dev_check_failure(struct eeh_dev *edev)
|
||||||
if (pe->state & EEH_PE_ISOLATED) {
|
if (pe->state & EEH_PE_ISOLATED) {
|
||||||
pe->check_count++;
|
pe->check_count++;
|
||||||
if (pe->check_count % EEH_MAX_FAILS == 0) {
|
if (pe->check_count % EEH_MAX_FAILS == 0) {
|
||||||
location = of_get_property(dn, "ibm,loc-code", NULL);
|
pdn = eeh_dev_to_pdn(edev);
|
||||||
|
if (pdn->node)
|
||||||
|
location = of_get_property(pdn->node, "ibm,loc-code", NULL);
|
||||||
printk(KERN_ERR "EEH: %d reads ignored for recovering device at "
|
printk(KERN_ERR "EEH: %d reads ignored for recovering device at "
|
||||||
"location=%s driver=%s pci addr=%s\n",
|
"location=%s driver=%s pci addr=%s\n",
|
||||||
pe->check_count, location,
|
pe->check_count,
|
||||||
|
location ? location : "unknown",
|
||||||
eeh_driver_name(dev), eeh_pci_name(dev));
|
eeh_driver_name(dev), eeh_pci_name(dev));
|
||||||
printk(KERN_ERR "EEH: Might be infinite loop in %s driver\n",
|
printk(KERN_ERR "EEH: Might be infinite loop in %s driver\n",
|
||||||
eeh_driver_name(dev));
|
eeh_driver_name(dev));
|
||||||
|
@ -1035,7 +1037,7 @@ int eeh_init(void)
|
||||||
core_initcall_sync(eeh_init);
|
core_initcall_sync(eeh_init);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* eeh_add_device_early - Enable EEH for the indicated device_node
|
* eeh_add_device_early - Enable EEH for the indicated device node
|
||||||
* @pdn: PCI device node for which to set up EEH
|
* @pdn: PCI device node for which to set up EEH
|
||||||
*
|
*
|
||||||
* This routine must be used to perform EEH initialization for PCI
|
* This routine must be used to perform EEH initialization for PCI
|
||||||
|
@ -1093,7 +1095,7 @@ EXPORT_SYMBOL_GPL(eeh_add_device_tree_early);
|
||||||
*/
|
*/
|
||||||
void eeh_add_device_late(struct pci_dev *dev)
|
void eeh_add_device_late(struct pci_dev *dev)
|
||||||
{
|
{
|
||||||
struct device_node *dn;
|
struct pci_dn *pdn;
|
||||||
struct eeh_dev *edev;
|
struct eeh_dev *edev;
|
||||||
|
|
||||||
if (!dev || !eeh_enabled())
|
if (!dev || !eeh_enabled())
|
||||||
|
@ -1101,8 +1103,8 @@ void eeh_add_device_late(struct pci_dev *dev)
|
||||||
|
|
||||||
pr_debug("EEH: Adding device %s\n", pci_name(dev));
|
pr_debug("EEH: Adding device %s\n", pci_name(dev));
|
||||||
|
|
||||||
dn = pci_device_to_OF_node(dev);
|
pdn = pci_get_pdn_by_devfn(dev->bus, dev->devfn);
|
||||||
edev = of_node_to_eeh_dev(dn);
|
edev = pdn_to_eeh_dev(pdn);
|
||||||
if (edev->pdev == dev) {
|
if (edev->pdev == dev) {
|
||||||
pr_debug("EEH: Already referenced !\n");
|
pr_debug("EEH: Already referenced !\n");
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -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)
|
||||||
*/
|
*/
|
||||||
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;
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -348,9 +348,12 @@ int eeh_add_to_parent_pe(struct eeh_dev *edev)
|
||||||
|
|
||||||
/* 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);
|
||||||
|
@ -366,9 +369,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -407,8 +415,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;
|
||||||
}
|
}
|
||||||
|
@ -428,8 +441,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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,
|
||||||
|
|
||||||
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;
|
||||||
|
|
|
@ -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)
|
||||||
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;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue