25 #include <linux/export.h>
28 #include <linux/kernel.h>
29 #include <linux/pci.h>
30 #include <linux/string.h>
32 #include <asm/pci-bridge.h>
49 pe = kzalloc(
sizeof(
struct eeh_pe),
GFP_KERNEL);
55 INIT_LIST_HEAD(&pe->child_list);
56 INIT_LIST_HEAD(&pe->child);
57 INIT_LIST_HEAD(&pe->edevs);
74 pe = eeh_pe_alloc(phb, EEH_PE_PHB);
76 pr_err(
"%s: out of memory!\n", __func__);
85 pr_debug(
"EEH: Add PE for PHB#%d\n", phb->global_number);
108 if ((pe->type & EEH_PE_PHB) && pe->phb == phb)
123 static struct eeh_pe *eeh_pe_next(
struct eeh_pe *pe,
128 if (next == &pe->child_list) {
132 next = pe->child.
next;
133 if (next != &pe->parent->child_list)
153 static void *eeh_pe_traverse(
struct eeh_pe *root,
154 eeh_traverse_func
fn,
void *
flag)
159 for (pe = root; pe; pe = eeh_pe_next(pe, root)) {
177 eeh_traverse_func fn,
void *flag)
180 struct eeh_dev *edev;
184 pr_warning(
"%s: Invalid PE %p\n", __func__, root);
191 for (pe = root; pe; pe = eeh_pe_next(pe, root)) {
192 eeh_pe_for_each_dev(pe, edev) {
193 ret =
fn(edev, flag);
216 static void *__eeh_pe_get(
void *
data,
void *flag)
218 struct eeh_pe *pe = (
struct eeh_pe *)data;
219 struct eeh_dev *edev = (
struct eeh_dev *)flag;
222 if (pe->type & EEH_PE_PHB)
226 if (edev->pe_config_addr &&
227 (edev->pe_config_addr == pe->addr))
231 if (edev->pe_config_addr &&
232 (edev->config_addr == pe->config_addr))
249 static struct eeh_pe *eeh_pe_get(
struct eeh_dev *edev)
251 struct eeh_pe *root = eeh_phb_pe_get(edev->phb);
254 pe = eeh_pe_traverse(root, __eeh_pe_get, edev);
267 static struct eeh_pe *eeh_pe_get_parent(
struct eeh_dev *edev)
280 if (!PCI_DN(dn))
return NULL;
282 parent = of_node_to_eeh_dev(dn);
284 if (!parent)
return NULL;
306 struct eeh_pe *pe, *parent;
316 pe = eeh_pe_get(edev);
317 if (pe && !(pe->type & EEH_PE_INVALID)) {
318 if (!edev->pe_config_addr) {
320 pr_err(
"%s: PE with addr 0x%x already exists\n",
321 __func__, edev->config_addr);
326 pe->type = EEH_PE_BUS;
332 pr_debug(
"EEH: Add %s to Bus PE#%x\n",
333 edev->dn->full_name, pe->addr);
336 }
else if (pe && (pe->type & EEH_PE_INVALID)) {
345 if (!(parent->type & EEH_PE_INVALID))
347 parent->type &= ~EEH_PE_INVALID;
348 parent = parent->parent;
351 pr_debug(
"EEH: Add %s to Device PE#%x, Parent PE#%x\n",
352 edev->dn->full_name, pe->addr, pe->parent->addr);
358 pe = eeh_pe_alloc(edev->phb, EEH_PE_DEVICE);
361 pr_err(
"%s: out of memory!\n", __func__);
364 pe->addr = edev->pe_config_addr;
365 pe->config_addr = edev->config_addr;
373 parent = eeh_pe_get_parent(edev);
375 parent = eeh_phb_pe_get(edev->phb);
378 pr_err(
"%s: No PHB PE is found (PHB Domain=%d)\n",
379 __func__, edev->phb->global_number);
395 pr_debug(
"EEH: Add %s to Device PE#%x, Parent PE#%x\n",
396 edev->dn->full_name, pe->addr, pe->parent->addr);
413 struct eeh_pe *pe, *parent, *
child;
417 pr_warning(
"%s: No PE found for EEH device %s\n",
418 __func__, edev->dn->full_name);
437 if (pe->type & EEH_PE_PHB)
441 if (list_empty(&pe->edevs) &&
442 list_empty(&pe->child_list)) {
449 if (list_empty(&pe->edevs)) {
452 if (!(child->type & EEH_PE_INVALID)) {
459 pe->type |= EEH_PE_INVALID;
482 static void *__eeh_pe_state_mark(
void *data,
void *flag)
484 struct eeh_pe *pe = (
struct eeh_pe *)data;
485 int state = *((
int *)flag);
496 eeh_pe_for_each_dev(pe, tmp) {
497 pdev = eeh_dev_to_pci_dev(tmp);
516 eeh_pe_traverse(pe, __eeh_pe_state_mark, &state);
529 static void *__eeh_pe_state_clear(
void *data,
void *flag)
531 struct eeh_pe *pe = (
struct eeh_pe *)data;
532 int state = *((
int *)flag);
552 eeh_pe_traverse(pe, __eeh_pe_state_clear, &state);
565 static void *eeh_restore_one_device_bars(
void *data,
void *flag)
569 struct eeh_dev *edev = (
struct eeh_dev *)data;
572 for (i = 4; i < 10; i++)
573 eeh_ops->write_config(dn, i*4, 4, edev->config_space[i]);
575 eeh_ops->write_config(dn, 12*4, 4, edev->config_space[12]);
577 #define BYTE_SWAP(OFF) (8*((OFF)/4)+3-(OFF))
578 #define SAVED_BYTE(OFF) (((u8 *)(edev->config_space))[BYTE_SWAP(OFF)])
586 eeh_ops->write_config(dn, 15*4, 4, edev->config_space[15]);
635 struct eeh_dev *edev;
640 if (pe->type & EEH_PE_PHB) {
642 }
else if (pe->type & EEH_PE_BUS) {
644 pdev = eeh_dev_to_pci_dev(edev);