diff options
| author | Gavin Shan <gwshan@linux.vnet.ibm.com> | 2015-03-17 01:15:05 -0400 |
|---|---|---|
| committer | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2015-03-23 22:15:51 -0400 |
| commit | e8e9b34cef237d4d6fdc0d350cd8a95d1adb9ee9 (patch) | |
| tree | aa6d7d2300e27e621af79b4a252ee9aa93a4a893 | |
| parent | c035ff1d2eaa03ab40839041e955a86a8e412eb4 (diff) | |
powerpc/eeh: Create eeh_dev from pci_dn instead of device_node
The patch adds function traverse_pci_dn(), which is similar to
traverse_pci_devices() except it takes pci_dn, not device_node
as parameter. The pci_dev.c has been reworked to create eeh_dev
from pci_dn, instead of device_node.
Signed-off-by: Gavin Shan <gwshan@linux.vnet.ibm.com>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
| -rw-r--r-- | arch/powerpc/include/asm/eeh.h | 11 | ||||
| -rw-r--r-- | arch/powerpc/include/asm/pci-bridge.h | 8 | ||||
| -rw-r--r-- | arch/powerpc/include/asm/ppc-pci.h | 5 | ||||
| -rw-r--r-- | arch/powerpc/kernel/eeh_dev.c | 14 | ||||
| -rw-r--r-- | arch/powerpc/kernel/pci_dn.c | 40 | ||||
| -rw-r--r-- | arch/powerpc/platforms/pseries/setup.c | 2 |
6 files changed, 69 insertions, 11 deletions
diff --git a/arch/powerpc/include/asm/eeh.h b/arch/powerpc/include/asm/eeh.h index 55abfd09e47f..2106f83da2d5 100644 --- a/arch/powerpc/include/asm/eeh.h +++ b/arch/powerpc/include/asm/eeh.h | |||
| @@ -30,6 +30,7 @@ | |||
| 30 | struct pci_dev; | 30 | struct pci_dev; |
| 31 | struct pci_bus; | 31 | struct pci_bus; |
| 32 | struct device_node; | 32 | struct device_node; |
| 33 | struct pci_dn; | ||
| 33 | 34 | ||
| 34 | #ifdef CONFIG_EEH | 35 | #ifdef CONFIG_EEH |
| 35 | 36 | ||
| @@ -137,6 +138,7 @@ struct eeh_dev { | |||
| 137 | struct list_head list; /* Form link list in the PE */ | 138 | struct list_head list; /* Form link list in the PE */ |
| 138 | struct pci_controller *phb; /* Associated PHB */ | 139 | struct pci_controller *phb; /* Associated PHB */ |
| 139 | struct device_node *dn; /* Associated device node */ | 140 | struct device_node *dn; /* Associated device node */ |
| 141 | struct pci_dn *pdn; /* Associated PCI device node */ | ||
| 140 | struct pci_dev *pdev; /* Associated PCI device */ | 142 | struct pci_dev *pdev; /* Associated PCI device */ |
| 141 | struct pci_bus *bus; /* PCI bus for partial hotplug */ | 143 | struct pci_bus *bus; /* PCI bus for partial hotplug */ |
| 142 | }; | 144 | }; |
| @@ -146,6 +148,11 @@ static inline struct device_node *eeh_dev_to_of_node(struct eeh_dev *edev) | |||
| 146 | return edev ? edev->dn : NULL; | 148 | return edev ? edev->dn : NULL; |
| 147 | } | 149 | } |
| 148 | 150 | ||
| 151 | static inline struct pci_dn *eeh_dev_to_pdn(struct eeh_dev *edev) | ||
| 152 | { | ||
| 153 | return edev ? edev->pdn : NULL; | ||
| 154 | } | ||
| 155 | |||
| 149 | static inline struct pci_dev *eeh_dev_to_pci_dev(struct eeh_dev *edev) | 156 | static inline struct pci_dev *eeh_dev_to_pci_dev(struct eeh_dev *edev) |
| 150 | { | 157 | { |
| 151 | return edev ? edev->pdev : NULL; | 158 | return edev ? edev->pdev : NULL; |
| @@ -272,7 +279,7 @@ void eeh_pe_restore_bars(struct eeh_pe *pe); | |||
| 272 | const char *eeh_pe_loc_get(struct eeh_pe *pe); | 279 | const char *eeh_pe_loc_get(struct eeh_pe *pe); |
| 273 | struct pci_bus *eeh_pe_bus_get(struct eeh_pe *pe); | 280 | struct pci_bus *eeh_pe_bus_get(struct eeh_pe *pe); |
| 274 | 281 | ||
| 275 | void *eeh_dev_init(struct device_node *dn, void *data); | 282 | void *eeh_dev_init(struct pci_dn *pdn, void *data); |
| 276 | void eeh_dev_phb_init_dynamic(struct pci_controller *phb); | 283 | void eeh_dev_phb_init_dynamic(struct pci_controller *phb); |
| 277 | int eeh_init(void); | 284 | int eeh_init(void); |
| 278 | int __init eeh_ops_register(struct eeh_ops *ops); | 285 | int __init eeh_ops_register(struct eeh_ops *ops); |
| @@ -323,7 +330,7 @@ static inline int eeh_init(void) | |||
| 323 | return 0; | 330 | return 0; |
| 324 | } | 331 | } |
| 325 | 332 | ||
| 326 | static inline void *eeh_dev_init(struct device_node *dn, void *data) | 333 | static inline void *eeh_dev_init(struct pci_dn *pdn, void *data) |
| 327 | { | 334 | { |
| 328 | return NULL; | 335 | return NULL; |
| 329 | } | 336 | } |
diff --git a/arch/powerpc/include/asm/pci-bridge.h b/arch/powerpc/include/asm/pci-bridge.h index 01b730a8a5a3..7b74499b728c 100644 --- a/arch/powerpc/include/asm/pci-bridge.h +++ b/arch/powerpc/include/asm/pci-bridge.h | |||
| @@ -213,8 +213,14 @@ static inline struct eeh_dev *of_node_to_eeh_dev(struct device_node *dn) | |||
| 213 | 213 | ||
| 214 | return PCI_DN(dn)->edev; | 214 | return PCI_DN(dn)->edev; |
| 215 | } | 215 | } |
| 216 | |||
| 217 | static inline struct eeh_dev *pdn_to_eeh_dev(struct pci_dn *pdn) | ||
| 218 | { | ||
| 219 | return pdn ? pdn->edev : NULL; | ||
| 220 | } | ||
| 216 | #else | 221 | #else |
| 217 | #define of_node_to_eeh_dev(x) (NULL) | 222 | #define of_node_to_eeh_dev(x) (NULL) |
| 223 | #define pdn_to_eeh_dev(x) (NULL) | ||
| 218 | #endif | 224 | #endif |
| 219 | 225 | ||
| 220 | /** Find the bus corresponding to the indicated device node */ | 226 | /** Find the bus corresponding to the indicated device node */ |
diff --git a/arch/powerpc/include/asm/ppc-pci.h b/arch/powerpc/include/asm/ppc-pci.h index db1e2b8eff3c..ade75238ceb5 100644 --- a/arch/powerpc/include/asm/ppc-pci.h +++ b/arch/powerpc/include/asm/ppc-pci.h | |||
| @@ -33,9 +33,14 @@ extern struct pci_dev *isa_bridge_pcidev; /* may be NULL if no ISA bus */ | |||
| 33 | 33 | ||
| 34 | /* PCI device_node operations */ | 34 | /* PCI device_node operations */ |
| 35 | struct device_node; | 35 | struct device_node; |
| 36 | struct pci_dn; | ||
| 37 | |||
| 36 | typedef void *(*traverse_func)(struct device_node *me, void *data); | 38 | typedef void *(*traverse_func)(struct device_node *me, void *data); |
| 37 | void *traverse_pci_devices(struct device_node *start, traverse_func pre, | 39 | void *traverse_pci_devices(struct device_node *start, traverse_func pre, |
| 38 | void *data); | 40 | void *data); |
| 41 | void *traverse_pci_dn(struct pci_dn *root, | ||
| 42 | void *(*fn)(struct pci_dn *, void *), | ||
| 43 | void *data); | ||
| 39 | 44 | ||
| 40 | extern void pci_devs_phb_init(void); | 45 | extern void pci_devs_phb_init(void); |
| 41 | extern void pci_devs_phb_init_dynamic(struct pci_controller *phb); | 46 | extern void pci_devs_phb_init_dynamic(struct pci_controller *phb); |
diff --git a/arch/powerpc/kernel/eeh_dev.c b/arch/powerpc/kernel/eeh_dev.c index e5274ee9a75f..aabba94ff9cb 100644 --- a/arch/powerpc/kernel/eeh_dev.c +++ b/arch/powerpc/kernel/eeh_dev.c | |||
| @@ -43,13 +43,13 @@ | |||
| 43 | 43 | ||
| 44 | /** | 44 | /** |
| 45 | * eeh_dev_init - Create EEH device according to OF node | 45 | * eeh_dev_init - Create EEH device according to OF node |
| 46 | * @dn: device node | 46 | * @pdn: PCI device node |
| 47 | * @data: PHB | 47 | * @data: PHB |
| 48 | * | 48 | * |
| 49 | * It will create EEH device according to the given OF node. The function | 49 | * It will create EEH device according to the given OF node. The function |
| 50 | * might be called by PCI emunation, DR, PHB hotplug. | 50 | * might be called by PCI emunation, DR, PHB hotplug. |
| 51 | */ | 51 | */ |
| 52 | void *eeh_dev_init(struct device_node *dn, void *data) | 52 | void *eeh_dev_init(struct pci_dn *pdn, void *data) |
| 53 | { | 53 | { |
| 54 | struct pci_controller *phb = data; | 54 | struct pci_controller *phb = data; |
| 55 | struct eeh_dev *edev; | 55 | struct eeh_dev *edev; |
| @@ -63,8 +63,8 @@ void *eeh_dev_init(struct device_node *dn, void *data) | |||
| 63 | } | 63 | } |
| 64 | 64 | ||
| 65 | /* Associate EEH device with OF node */ | 65 | /* Associate EEH device with OF node */ |
| 66 | PCI_DN(dn)->edev = edev; | 66 | pdn->edev = edev; |
| 67 | edev->dn = dn; | 67 | edev->pdn = pdn; |
| 68 | edev->phb = phb; | 68 | edev->phb = phb; |
| 69 | INIT_LIST_HEAD(&edev->list); | 69 | INIT_LIST_HEAD(&edev->list); |
| 70 | 70 | ||
| @@ -80,16 +80,16 @@ void *eeh_dev_init(struct device_node *dn, void *data) | |||
| 80 | */ | 80 | */ |
| 81 | void eeh_dev_phb_init_dynamic(struct pci_controller *phb) | 81 | void eeh_dev_phb_init_dynamic(struct pci_controller *phb) |
| 82 | { | 82 | { |
| 83 | struct device_node *dn = phb->dn; | 83 | struct pci_dn *root = phb->pci_data; |
| 84 | 84 | ||
| 85 | /* EEH PE for PHB */ | 85 | /* EEH PE for PHB */ |
| 86 | eeh_phb_pe_create(phb); | 86 | eeh_phb_pe_create(phb); |
| 87 | 87 | ||
| 88 | /* EEH device for PHB */ | 88 | /* EEH device for PHB */ |
| 89 | eeh_dev_init(dn, phb); | 89 | eeh_dev_init(root, phb); |
| 90 | 90 | ||
| 91 | /* EEH devices for children OF nodes */ | 91 | /* EEH devices for children OF nodes */ |
| 92 | traverse_pci_devices(dn, eeh_dev_init, phb); | 92 | traverse_pci_dn(root, eeh_dev_init, phb); |
| 93 | } | 93 | } |
| 94 | 94 | ||
| 95 | /** | 95 | /** |
diff --git a/arch/powerpc/kernel/pci_dn.c b/arch/powerpc/kernel/pci_dn.c index d139f72ff9d5..65b98367005c 100644 --- a/arch/powerpc/kernel/pci_dn.c +++ b/arch/powerpc/kernel/pci_dn.c | |||
| @@ -246,6 +246,46 @@ void *traverse_pci_devices(struct device_node *start, traverse_func pre, | |||
| 246 | return NULL; | 246 | return NULL; |
| 247 | } | 247 | } |
| 248 | 248 | ||
| 249 | static struct pci_dn *pci_dn_next_one(struct pci_dn *root, | ||
| 250 | struct pci_dn *pdn) | ||
| 251 | { | ||
| 252 | struct list_head *next = pdn->child_list.next; | ||
| 253 | |||
| 254 | if (next != &pdn->child_list) | ||
| 255 | return list_entry(next, struct pci_dn, list); | ||
| 256 | |||
| 257 | while (1) { | ||
| 258 | if (pdn == root) | ||
| 259 | return NULL; | ||
| 260 | |||
| 261 | next = pdn->list.next; | ||
| 262 | if (next != &pdn->parent->child_list) | ||
| 263 | break; | ||
| 264 | |||
| 265 | pdn = pdn->parent; | ||
| 266 | } | ||
| 267 | |||
| 268 | return list_entry(next, struct pci_dn, list); | ||
| 269 | } | ||
| 270 | |||
| 271 | void *traverse_pci_dn(struct pci_dn *root, | ||
| 272 | void *(*fn)(struct pci_dn *, void *), | ||
| 273 | void *data) | ||
| 274 | { | ||
| 275 | struct pci_dn *pdn = root; | ||
| 276 | void *ret; | ||
| 277 | |||
| 278 | /* Only scan the child nodes */ | ||
| 279 | for (pdn = pci_dn_next_one(root, pdn); pdn; | ||
| 280 | pdn = pci_dn_next_one(root, pdn)) { | ||
| 281 | ret = fn(pdn, data); | ||
| 282 | if (ret) | ||
| 283 | return ret; | ||
| 284 | } | ||
| 285 | |||
| 286 | return NULL; | ||
| 287 | } | ||
| 288 | |||
| 249 | /** | 289 | /** |
| 250 | * pci_devs_phb_init_dynamic - setup pci devices under this PHB | 290 | * pci_devs_phb_init_dynamic - setup pci devices under this PHB |
| 251 | * phb: pci-to-host bridge (top-level bridge connecting to cpu) | 291 | * phb: pci-to-host bridge (top-level bridge connecting to cpu) |
diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c index e445b6701f50..70304070a260 100644 --- a/arch/powerpc/platforms/pseries/setup.c +++ b/arch/powerpc/platforms/pseries/setup.c | |||
| @@ -265,7 +265,7 @@ static int pci_dn_reconfig_notifier(struct notifier_block *nb, unsigned long act | |||
| 265 | update_dn_pci_info(np, pci->phb); | 265 | update_dn_pci_info(np, pci->phb); |
| 266 | 266 | ||
| 267 | /* Create EEH device for the OF node */ | 267 | /* Create EEH device for the OF node */ |
| 268 | eeh_dev_init(np, pci->phb); | 268 | eeh_dev_init(PCI_DN(np), pci->phb); |
| 269 | } | 269 | } |
| 270 | break; | 270 | break; |
| 271 | default: | 271 | default: |
