Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Gavin Shan and committed by
Benjamin Herrenschmidt
e8e9b34c c035ff1d

+69 -11
+9 -2
arch/powerpc/include/asm/eeh.h
··· 30 30 struct pci_dev; 31 31 struct pci_bus; 32 32 struct device_node; 33 + struct pci_dn; 33 34 34 35 #ifdef CONFIG_EEH 35 36 ··· 138 137 struct list_head list; /* Form link list in the PE */ 139 138 struct pci_controller *phb; /* Associated PHB */ 140 139 struct device_node *dn; /* Associated device node */ 140 + struct pci_dn *pdn; /* Associated PCI device node */ 141 141 struct pci_dev *pdev; /* Associated PCI device */ 142 142 struct pci_bus *bus; /* PCI bus for partial hotplug */ 143 143 }; ··· 146 144 static inline struct device_node *eeh_dev_to_of_node(struct eeh_dev *edev) 147 145 { 148 146 return edev ? edev->dn : NULL; 147 + } 148 + 149 + static inline struct pci_dn *eeh_dev_to_pdn(struct eeh_dev *edev) 150 + { 151 + return edev ? edev->pdn : NULL; 149 152 } 150 153 151 154 static inline struct pci_dev *eeh_dev_to_pci_dev(struct eeh_dev *edev) ··· 279 272 const char *eeh_pe_loc_get(struct eeh_pe *pe); 280 273 struct pci_bus *eeh_pe_bus_get(struct eeh_pe *pe); 281 274 282 - void *eeh_dev_init(struct device_node *dn, void *data); 275 + void *eeh_dev_init(struct pci_dn *pdn, void *data); 283 276 void eeh_dev_phb_init_dynamic(struct pci_controller *phb); 284 277 int eeh_init(void); 285 278 int __init eeh_ops_register(struct eeh_ops *ops); ··· 330 323 return 0; 331 324 } 332 325 333 - static inline void *eeh_dev_init(struct device_node *dn, void *data) 326 + static inline void *eeh_dev_init(struct pci_dn *pdn, void *data) 334 327 { 335 328 return NULL; 336 329 }
+7 -1
arch/powerpc/include/asm/pci-bridge.h
··· 213 213 214 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 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 224 #endif 219 225 220 226 /** Find the bus corresponding to the indicated device node */
+5
arch/powerpc/include/asm/ppc-pci.h
··· 33 33 34 34 /* PCI device_node operations */ 35 35 struct device_node; 36 + struct pci_dn; 37 + 36 38 typedef void *(*traverse_func)(struct device_node *me, void *data); 37 39 void *traverse_pci_devices(struct device_node *start, traverse_func pre, 38 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 45 extern void pci_devs_phb_init(void); 41 46 extern void pci_devs_phb_init_dynamic(struct pci_controller *phb);
+7 -7
arch/powerpc/kernel/eeh_dev.c
··· 43 43 44 44 /** 45 45 * eeh_dev_init - Create EEH device according to OF node 46 - * @dn: device node 46 + * @pdn: PCI device node 47 47 * @data: PHB 48 48 * 49 49 * It will create EEH device according to the given OF node. The function 50 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 54 struct pci_controller *phb = data; 55 55 struct eeh_dev *edev; ··· 63 63 } 64 64 65 65 /* Associate EEH device with OF node */ 66 - PCI_DN(dn)->edev = edev; 67 - edev->dn = dn; 66 + pdn->edev = edev; 67 + edev->pdn = pdn; 68 68 edev->phb = phb; 69 69 INIT_LIST_HEAD(&edev->list); 70 70 ··· 80 80 */ 81 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 85 /* EEH PE for PHB */ 86 86 eeh_phb_pe_create(phb); 87 87 88 88 /* EEH device for PHB */ 89 - eeh_dev_init(dn, phb); 89 + eeh_dev_init(root, phb); 90 90 91 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 /**
+40
arch/powerpc/kernel/pci_dn.c
··· 246 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 290 * pci_devs_phb_init_dynamic - setup pci devices under this PHB 251 291 * phb: pci-to-host bridge (top-level bridge connecting to cpu)
+1 -1
arch/powerpc/platforms/pseries/setup.c
··· 265 265 update_dn_pci_info(np, pci->phb); 266 266 267 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 270 break; 271 271 default: