Commit f8f7d63fd96ead101415a1302035137a866f8998

Authored by Gavin Shan
Committed by Benjamin Herrenschmidt
1 parent d7bb88629d

powerpc/eeh: Trace eeh device from I/O cache

The idea comes from Benjamin Herrenschmidt. The eeh cache helps
fetching the pci device according to the given I/O address. Since
the eeh cache is serving for eeh, it's reasonable for eeh cache
to trace eeh device except pci device.

The patch make eeh cache to trace eeh device. Also, the major
eeh entry function eeh_dn_check_failure has been renamed to
eeh_dev_check_failure since it will take eeh device as input
parameter.

Signed-off-by: Gavin Shan <shangw@linux.vnet.ibm.com>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>

Showing 6 changed files with 28 additions and 32 deletions Side-by-side Diff

arch/powerpc/include/asm/eeh.h
... ... @@ -196,7 +196,7 @@
196 196 int __exit eeh_ops_unregister(const char *name);
197 197 unsigned long eeh_check_failure(const volatile void __iomem *token,
198 198 unsigned long val);
199   -int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev);
  199 +int eeh_dev_check_failure(struct eeh_dev *edev);
200 200 void __init pci_addr_cache_build(void);
201 201 void eeh_add_device_tree_early(struct device_node *);
202 202 void eeh_add_device_tree_late(struct pci_bus *);
... ... @@ -231,10 +231,7 @@
231 231 return val;
232 232 }
233 233  
234   -static inline int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev)
235   -{
236   - return 0;
237   -}
  234 +#define eeh_dev_check_failure(x) (0)
238 235  
239 236 static inline void pci_addr_cache_build(void) { }
240 237  
arch/powerpc/include/asm/pci-bridge.h
... ... @@ -184,6 +184,8 @@
184 184 {
185 185 return PCI_DN(dn)->edev;
186 186 }
  187 +#else
  188 +#define of_node_to_eeh_dev(x) (NULL)
187 189 #endif
188 190  
189 191 /** Find the bus corresponding to the indicated device node */
arch/powerpc/include/asm/ppc-pci.h
... ... @@ -50,7 +50,7 @@
50 50 void pci_addr_cache_build(void);
51 51 void pci_addr_cache_insert_device(struct pci_dev *dev);
52 52 void pci_addr_cache_remove_device(struct pci_dev *dev);
53   -struct pci_dev *pci_addr_cache_get_device(unsigned long addr);
  53 +struct eeh_dev *pci_addr_cache_get_device(unsigned long addr);
54 54 void eeh_slot_error_detail(struct eeh_pe *pe, int severity);
55 55 int eeh_pci_enable(struct eeh_pe *pe, int function);
56 56 int eeh_reset_pe(struct eeh_pe *);
arch/powerpc/kernel/rtas_pci.c
... ... @@ -81,7 +81,7 @@
81 81 return PCIBIOS_DEVICE_NOT_FOUND;
82 82  
83 83 if (returnval == EEH_IO_ERROR_VALUE(size) &&
84   - eeh_dn_check_failure (pdn->node, NULL))
  84 + eeh_dev_check_failure(of_node_to_eeh_dev(pdn->node)))
85 85 return PCIBIOS_DEVICE_NOT_FOUND;
86 86  
87 87 return PCIBIOS_SUCCESSFUL;
arch/powerpc/platforms/pseries/eeh.c
... ... @@ -270,9 +270,8 @@
270 270 }
271 271  
272 272 /**
273   - * eeh_dn_check_failure - Check if all 1's data is due to EEH slot freeze
274   - * @dn: device node
275   - * @dev: pci device, if known
  273 + * eeh_dev_check_failure - Check if all 1's data is due to EEH slot freeze
  274 + * @edev: eeh device
276 275 *
277 276 * Check for an EEH failure for the given device node. Call this
278 277 * routine if the result of a read was all 0xff's and you want to
279 278  
280 279  
... ... @@ -284,12 +283,13 @@
284 283 *
285 284 * It is safe to call this routine in an interrupt context.
286 285 */
287   -int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev)
  286 +int eeh_dev_check_failure(struct eeh_dev *edev)
288 287 {
289 288 int ret;
290 289 unsigned long flags;
  290 + struct device_node *dn;
  291 + struct pci_dev *dev;
291 292 struct eeh_pe *pe;
292   - struct eeh_dev *edev;
293 293 int rc = 0;
294 294 const char *location;
295 295  
296 296  
... ... @@ -298,15 +298,12 @@
298 298 if (!eeh_subsystem_enabled)
299 299 return 0;
300 300  
301   - if (dn) {
302   - edev = of_node_to_eeh_dev(dn);
303   - } else if (dev) {
304   - edev = pci_dev_to_eeh_dev(dev);
305   - dn = pci_device_to_OF_node(dev);
306   - } else {
  301 + if (!edev) {
307 302 eeh_stats.no_dn++;
308 303 return 0;
309 304 }
  305 + dn = eeh_dev_to_of_node(edev);
  306 + dev = eeh_dev_to_pci_dev(edev);
310 307 pe = edev->pe;
311 308  
312 309 /* Access to IO BARs might get this far and still not want checking. */
... ... @@ -393,7 +390,7 @@
393 390 return rc;
394 391 }
395 392  
396   -EXPORT_SYMBOL_GPL(eeh_dn_check_failure);
  393 +EXPORT_SYMBOL_GPL(eeh_dev_check_failure);
397 394  
398 395 /**
399 396 * eeh_check_failure - Check if all 1's data is due to EEH slot freeze
400 397  
401 398  
402 399  
... ... @@ -410,21 +407,19 @@
410 407 unsigned long eeh_check_failure(const volatile void __iomem *token, unsigned long val)
411 408 {
412 409 unsigned long addr;
413   - struct pci_dev *dev;
414   - struct device_node *dn;
  410 + struct eeh_dev *edev;
415 411  
416 412 /* Finding the phys addr + pci device; this is pretty quick. */
417 413 addr = eeh_token_to_phys((unsigned long __force) token);
418   - dev = pci_addr_cache_get_device(addr);
419   - if (!dev) {
  414 + edev = pci_addr_cache_get_device(addr);
  415 + if (!edev) {
420 416 eeh_stats.no_device++;
421 417 return val;
422 418 }
423 419  
424   - dn = pci_device_to_OF_node(dev);
425   - eeh_dn_check_failure(dn, dev);
  420 + eeh_dev_check_failure(edev);
426 421  
427   - pci_dev_put(dev);
  422 + pci_dev_put(eeh_dev_to_pci_dev(edev));
428 423 return val;
429 424 }
430 425  
arch/powerpc/platforms/pseries/eeh_cache.c
... ... @@ -50,6 +50,7 @@
50 50 struct rb_node rb_node;
51 51 unsigned long addr_lo;
52 52 unsigned long addr_hi;
  53 + struct eeh_dev *edev;
53 54 struct pci_dev *pcidev;
54 55 unsigned int flags;
55 56 };
... ... @@ -59,7 +60,7 @@
59 60 spinlock_t piar_lock;
60 61 } pci_io_addr_cache_root;
61 62  
62   -static inline struct pci_dev *__pci_addr_cache_get_device(unsigned long addr)
  63 +static inline struct eeh_dev *__pci_addr_cache_get_device(unsigned long addr)
63 64 {
64 65 struct rb_node *n = pci_io_addr_cache_root.rb_root.rb_node;
65 66  
... ... @@ -74,7 +75,7 @@
74 75 n = n->rb_right;
75 76 } else {
76 77 pci_dev_get(piar->pcidev);
77   - return piar->pcidev;
  78 + return piar->edev;
78 79 }
79 80 }
80 81 }
81 82  
82 83  
83 84  
... ... @@ -92,15 +93,15 @@
92 93 * from zero (that is, they do *not* have pci_io_addr added in).
93 94 * It is safe to call this function within an interrupt.
94 95 */
95   -struct pci_dev *pci_addr_cache_get_device(unsigned long addr)
  96 +struct eeh_dev *pci_addr_cache_get_device(unsigned long addr)
96 97 {
97   - struct pci_dev *dev;
  98 + struct eeh_dev *edev;
98 99 unsigned long flags;
99 100  
100 101 spin_lock_irqsave(&pci_io_addr_cache_root.piar_lock, flags);
101   - dev = __pci_addr_cache_get_device(addr);
  102 + edev = __pci_addr_cache_get_device(addr);
102 103 spin_unlock_irqrestore(&pci_io_addr_cache_root.piar_lock, flags);
103   - return dev;
  104 + return edev;
104 105 }
105 106  
106 107 #ifdef DEBUG
... ... @@ -158,6 +159,7 @@
158 159 pci_dev_get(dev);
159 160 piar->addr_lo = alo;
160 161 piar->addr_hi = ahi;
  162 + piar->edev = pci_dev_to_eeh_dev(dev);
161 163 piar->pcidev = dev;
162 164 piar->flags = flags;
163 165