diff options
-rw-r--r-- | arch/powerpc/include/asm/eeh.h | 26 | ||||
-rw-r--r-- | arch/powerpc/include/asm/ppc-pci.h | 71 | ||||
-rw-r--r-- | arch/powerpc/platforms/pseries/eeh.c | 400 |
3 files changed, 276 insertions, 221 deletions
diff --git a/arch/powerpc/include/asm/eeh.h b/arch/powerpc/include/asm/eeh.h index 66ea9b8b95c5..232887721ff4 100644 --- a/arch/powerpc/include/asm/eeh.h +++ b/arch/powerpc/include/asm/eeh.h | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * eeh.h | ||
3 | * Copyright (C) 2001 Dave Engebretsen & Todd Inglett IBM Corporation. | 2 | * Copyright (C) 2001 Dave Engebretsen & Todd Inglett IBM Corporation. |
3 | * Copyright 2001-2012 IBM Corporation. | ||
4 | * | 4 | * |
5 | * This program is free software; you can redistribute it and/or modify | 5 | * This program is free software; you can redistribute it and/or modify |
6 | * it under the terms of the GNU General Public License as published by | 6 | * it under the terms of the GNU General Public License as published by |
@@ -40,8 +40,10 @@ extern int eeh_subsystem_enabled; | |||
40 | #define EEH_MODE_RECOVERING (1<<3) | 40 | #define EEH_MODE_RECOVERING (1<<3) |
41 | #define EEH_MODE_IRQ_DISABLED (1<<4) | 41 | #define EEH_MODE_IRQ_DISABLED (1<<4) |
42 | 42 | ||
43 | /* Max number of EEH freezes allowed before we consider the device | 43 | /* |
44 | * to be permanently disabled. */ | 44 | * Max number of EEH freezes allowed before we consider the device |
45 | * to be permanently disabled. | ||
46 | */ | ||
45 | #define EEH_MAX_ALLOWED_FREEZES 5 | 47 | #define EEH_MAX_ALLOWED_FREEZES 5 |
46 | 48 | ||
47 | void __init eeh_init(void); | 49 | void __init eeh_init(void); |
@@ -49,26 +51,8 @@ unsigned long eeh_check_failure(const volatile void __iomem *token, | |||
49 | unsigned long val); | 51 | unsigned long val); |
50 | int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev); | 52 | int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev); |
51 | void __init pci_addr_cache_build(void); | 53 | void __init pci_addr_cache_build(void); |
52 | |||
53 | /** | ||
54 | * eeh_add_device_early | ||
55 | * eeh_add_device_late | ||
56 | * | ||
57 | * Perform eeh initialization for devices added after boot. | ||
58 | * Call eeh_add_device_early before doing any i/o to the | ||
59 | * device (including config space i/o). Call eeh_add_device_late | ||
60 | * to finish the eeh setup for this device. | ||
61 | */ | ||
62 | void eeh_add_device_tree_early(struct device_node *); | 54 | void eeh_add_device_tree_early(struct device_node *); |
63 | void eeh_add_device_tree_late(struct pci_bus *); | 55 | void eeh_add_device_tree_late(struct pci_bus *); |
64 | |||
65 | /** | ||
66 | * eeh_remove_device_recursive - undo EEH for device & children. | ||
67 | * @dev: pci device to be removed | ||
68 | * | ||
69 | * As above, this removes the device; it also removes child | ||
70 | * pci devices as well. | ||
71 | */ | ||
72 | void eeh_remove_bus_device(struct pci_dev *); | 56 | void eeh_remove_bus_device(struct pci_dev *); |
73 | 57 | ||
74 | /** | 58 | /** |
diff --git a/arch/powerpc/include/asm/ppc-pci.h b/arch/powerpc/include/asm/ppc-pci.h index 6d422979ebaf..221d82fd8231 100644 --- a/arch/powerpc/include/asm/ppc-pci.h +++ b/arch/powerpc/include/asm/ppc-pci.h | |||
@@ -47,92 +47,27 @@ extern int rtas_setup_phb(struct pci_controller *phb); | |||
47 | 47 | ||
48 | extern unsigned long pci_probe_only; | 48 | extern unsigned long pci_probe_only; |
49 | 49 | ||
50 | /* ---- EEH internal-use-only related routines ---- */ | ||
51 | #ifdef CONFIG_EEH | 50 | #ifdef CONFIG_EEH |
52 | 51 | ||
53 | void pci_addr_cache_insert_device(struct pci_dev *dev); | 52 | void pci_addr_cache_insert_device(struct pci_dev *dev); |
54 | void pci_addr_cache_remove_device(struct pci_dev *dev); | 53 | void pci_addr_cache_remove_device(struct pci_dev *dev); |
55 | void pci_addr_cache_build(void); | 54 | void pci_addr_cache_build(void); |
56 | struct pci_dev *pci_get_device_by_addr(unsigned long addr); | 55 | struct pci_dev *pci_get_device_by_addr(unsigned long addr); |
57 | |||
58 | /** | ||
59 | * eeh_slot_error_detail -- record and EEH error condition to the log | ||
60 | * @pdn: pci device node | ||
61 | * @severity: EEH_LOG_TEMP_FAILURE or EEH_LOG_PERM_FAILURE | ||
62 | * | ||
63 | * Obtains the EEH error details from the RTAS subsystem, | ||
64 | * and then logs these details with the RTAS error log system. | ||
65 | */ | ||
66 | #define EEH_LOG_TEMP_FAILURE 1 | 56 | #define EEH_LOG_TEMP_FAILURE 1 |
67 | #define EEH_LOG_PERM_FAILURE 2 | 57 | #define EEH_LOG_PERM_FAILURE 2 |
68 | void eeh_slot_error_detail (struct pci_dn *pdn, int severity); | 58 | void eeh_slot_error_detail (struct pci_dn *pdn, int severity); |
69 | |||
70 | /** | ||
71 | * rtas_pci_enable - enable IO transfers for this slot | ||
72 | * @pdn: pci device node | ||
73 | * @function: either EEH_THAW_MMIO or EEH_THAW_DMA | ||
74 | * | ||
75 | * Enable I/O transfers to this slot | ||
76 | */ | ||
77 | #define EEH_THAW_MMIO 2 | 59 | #define EEH_THAW_MMIO 2 |
78 | #define EEH_THAW_DMA 3 | 60 | #define EEH_THAW_DMA 3 |
79 | int rtas_pci_enable(struct pci_dn *pdn, int function); | 61 | int rtas_pci_enable(struct pci_dn *pdn, int function); |
80 | |||
81 | /** | ||
82 | * rtas_set_slot_reset -- unfreeze a frozen slot | ||
83 | * @pdn: pci device node | ||
84 | * | ||
85 | * Clear the EEH-frozen condition on a slot. This routine | ||
86 | * does this by asserting the PCI #RST line for 1/8th of | ||
87 | * a second; this routine will sleep while the adapter is | ||
88 | * being reset. | ||
89 | * | ||
90 | * Returns a non-zero value if the reset failed. | ||
91 | */ | ||
92 | int rtas_set_slot_reset (struct pci_dn *); | 62 | int rtas_set_slot_reset (struct pci_dn *); |
93 | int eeh_wait_for_slot_status(struct pci_dn *pdn, int max_wait_msecs); | 63 | int eeh_wait_for_slot_status(struct pci_dn *pdn, int max_wait_msecs); |
94 | |||
95 | /** | ||
96 | * eeh_restore_bars - Restore device configuration info. | ||
97 | * @pdn: pci device node | ||
98 | * | ||
99 | * A reset of a PCI device will clear out its config space. | ||
100 | * This routines will restore the config space for this | ||
101 | * device, and is children, to values previously obtained | ||
102 | * from the firmware. | ||
103 | */ | ||
104 | void eeh_restore_bars(struct pci_dn *); | 64 | void eeh_restore_bars(struct pci_dn *); |
105 | |||
106 | /** | ||
107 | * rtas_configure_bridge -- firmware initialization of pci bridge | ||
108 | * @pdn: pci device node | ||
109 | * | ||
110 | * Ask the firmware to configure all PCI bridges devices | ||
111 | * located behind the indicated node. Required after a | ||
112 | * pci device reset. Does essentially the same hing as | ||
113 | * eeh_restore_bars, but for brdges, and lets firmware | ||
114 | * do the work. | ||
115 | */ | ||
116 | void rtas_configure_bridge(struct pci_dn *); | 65 | void rtas_configure_bridge(struct pci_dn *); |
117 | |||
118 | int rtas_write_config(struct pci_dn *, int where, int size, u32 val); | 66 | int rtas_write_config(struct pci_dn *, int where, int size, u32 val); |
119 | int rtas_read_config(struct pci_dn *, int where, int size, u32 *val); | 67 | int rtas_read_config(struct pci_dn *, int where, int size, u32 *val); |
120 | 68 | void eeh_mark_slot(struct device_node *dn, int mode_flag); | |
121 | /** | 69 | void eeh_clear_slot(struct device_node *dn, int mode_flag); |
122 | * eeh_mark_slot -- set mode flags for pertition endpoint | 70 | struct device_node *find_device_pe(struct device_node *dn); |
123 | * @pdn: pci device node | ||
124 | * | ||
125 | * mark and clear slots: find "partition endpoint" PE and set or | ||
126 | * clear the flags for each subnode of the PE. | ||
127 | */ | ||
128 | void eeh_mark_slot (struct device_node *dn, int mode_flag); | ||
129 | void eeh_clear_slot (struct device_node *dn, int mode_flag); | ||
130 | |||
131 | /** | ||
132 | * find_device_pe -- Find the associated "Partiationable Endpoint" PE | ||
133 | * @pdn: pci device node | ||
134 | */ | ||
135 | struct device_node * find_device_pe(struct device_node *dn); | ||
136 | 71 | ||
137 | void eeh_sysfs_add_device(struct pci_dev *pdev); | 72 | void eeh_sysfs_add_device(struct pci_dev *pdev); |
138 | void eeh_sysfs_remove_device(struct pci_dev *pdev); | 73 | void eeh_sysfs_remove_device(struct pci_dev *pdev); |
diff --git a/arch/powerpc/platforms/pseries/eeh.c b/arch/powerpc/platforms/pseries/eeh.c index c0b40af4ce4f..5f6d37bdd4f5 100644 --- a/arch/powerpc/platforms/pseries/eeh.c +++ b/arch/powerpc/platforms/pseries/eeh.c | |||
@@ -1,8 +1,8 @@ | |||
1 | /* | 1 | /* |
2 | * eeh.c | ||
3 | * Copyright IBM Corporation 2001, 2005, 2006 | 2 | * Copyright IBM Corporation 2001, 2005, 2006 |
4 | * Copyright Dave Engebretsen & Todd Inglett 2001 | 3 | * Copyright Dave Engebretsen & Todd Inglett 2001 |
5 | * Copyright Linas Vepstas 2005, 2006 | 4 | * Copyright Linas Vepstas 2005, 2006 |
5 | * Copyright 2001-2012 IBM Corporation. | ||
6 | * | 6 | * |
7 | * This program is free software; you can redistribute it and/or modify | 7 | * This program is free software; you can redistribute it and/or modify |
8 | * it under the terms of the GNU General Public License as published by | 8 | * it under the terms of the GNU General Public License as published by |
@@ -22,7 +22,7 @@ | |||
22 | */ | 22 | */ |
23 | 23 | ||
24 | #include <linux/delay.h> | 24 | #include <linux/delay.h> |
25 | #include <linux/sched.h> /* for init_mm */ | 25 | #include <linux/sched.h> |
26 | #include <linux/init.h> | 26 | #include <linux/init.h> |
27 | #include <linux/list.h> | 27 | #include <linux/list.h> |
28 | #include <linux/pci.h> | 28 | #include <linux/pci.h> |
@@ -129,9 +129,16 @@ static unsigned long slot_resets; | |||
129 | 129 | ||
130 | #define IS_BRIDGE(class_code) (((class_code)<<16) == PCI_BASE_CLASS_BRIDGE) | 130 | #define IS_BRIDGE(class_code) (((class_code)<<16) == PCI_BASE_CLASS_BRIDGE) |
131 | 131 | ||
132 | /* --------------------------------------------------------------- */ | 132 | /** |
133 | /* Below lies the EEH event infrastructure */ | 133 | * rtas_slot_error_detail - Retrieve error log through RTAS call |
134 | 134 | * @pdn: device node | |
135 | * @severity: temporary or permanent error log | ||
136 | * @driver_log: driver log to be combined with the retrieved error log | ||
137 | * @loglen: length of driver log | ||
138 | * | ||
139 | * This routine should be called to retrieve error log through the dedicated | ||
140 | * RTAS call. | ||
141 | */ | ||
135 | static void rtas_slot_error_detail(struct pci_dn *pdn, int severity, | 142 | static void rtas_slot_error_detail(struct pci_dn *pdn, int severity, |
136 | char *driver_log, size_t loglen) | 143 | char *driver_log, size_t loglen) |
137 | { | 144 | { |
@@ -163,7 +170,7 @@ static void rtas_slot_error_detail(struct pci_dn *pdn, int severity, | |||
163 | } | 170 | } |
164 | 171 | ||
165 | /** | 172 | /** |
166 | * gather_pci_data - copy assorted PCI config space registers to buff | 173 | * gather_pci_data - Copy assorted PCI config space registers to buff |
167 | * @pdn: device to report data for | 174 | * @pdn: device to report data for |
168 | * @buf: point to buffer in which to log | 175 | * @buf: point to buffer in which to log |
169 | * @len: amount of room in buffer | 176 | * @len: amount of room in buffer |
@@ -258,6 +265,16 @@ static size_t gather_pci_data(struct pci_dn *pdn, char * buf, size_t len) | |||
258 | return n; | 265 | return n; |
259 | } | 266 | } |
260 | 267 | ||
268 | /** | ||
269 | * eeh_slot_error_detail - Generate combined log including driver log and error log | ||
270 | * @pdn: device node | ||
271 | * @severity: temporary or permanent error log | ||
272 | * | ||
273 | * This routine should be called to generate the combined log, which | ||
274 | * is comprised of driver log and error log. The driver log is figured | ||
275 | * out from the config space of the corresponding PCI device, while | ||
276 | * the error log is fetched through platform dependent function call. | ||
277 | */ | ||
261 | void eeh_slot_error_detail(struct pci_dn *pdn, int severity) | 278 | void eeh_slot_error_detail(struct pci_dn *pdn, int severity) |
262 | { | 279 | { |
263 | size_t loglen = 0; | 280 | size_t loglen = 0; |
@@ -275,6 +292,9 @@ void eeh_slot_error_detail(struct pci_dn *pdn, int severity) | |||
275 | * read_slot_reset_state - Read the reset state of a device node's slot | 292 | * read_slot_reset_state - Read the reset state of a device node's slot |
276 | * @dn: device node to read | 293 | * @dn: device node to read |
277 | * @rets: array to return results in | 294 | * @rets: array to return results in |
295 | * | ||
296 | * Read the reset state of a device node's slot through platform dependent | ||
297 | * function call. | ||
278 | */ | 298 | */ |
279 | static int read_slot_reset_state(struct pci_dn *pdn, int rets[]) | 299 | static int read_slot_reset_state(struct pci_dn *pdn, int rets[]) |
280 | { | 300 | { |
@@ -300,9 +320,9 @@ static int read_slot_reset_state(struct pci_dn *pdn, int rets[]) | |||
300 | } | 320 | } |
301 | 321 | ||
302 | /** | 322 | /** |
303 | * eeh_wait_for_slot_status - returns error status of slot | 323 | * eeh_wait_for_slot_status - Returns error status of slot |
304 | * @pdn pci device node | 324 | * @pdn: pci device node |
305 | * @max_wait_msecs maximum number to millisecs to wait | 325 | * @max_wait_msecs: maximum number to millisecs to wait |
306 | * | 326 | * |
307 | * Return negative value if a permanent error, else return | 327 | * Return negative value if a permanent error, else return |
308 | * Partition Endpoint (PE) status value. | 328 | * Partition Endpoint (PE) status value. |
@@ -332,16 +352,16 @@ eeh_wait_for_slot_status(struct pci_dn *pdn, int max_wait_msecs) | |||
332 | 352 | ||
333 | mwait = rets[2]; | 353 | mwait = rets[2]; |
334 | if (mwait <= 0) { | 354 | if (mwait <= 0) { |
335 | printk (KERN_WARNING | 355 | printk(KERN_WARNING "EEH: Firmware returned bad wait value=%d\n", |
336 | "EEH: Firmware returned bad wait value=%d\n", mwait); | 356 | mwait); |
337 | mwait = 1000; | 357 | mwait = 1000; |
338 | } else if (mwait > 300*1000) { | 358 | } else if (mwait > 300*1000) { |
339 | printk (KERN_WARNING | 359 | printk(KERN_WARNING "EEH: Firmware is taking too long, time=%d\n", |
340 | "EEH: Firmware is taking too long, time=%d\n", mwait); | 360 | mwait); |
341 | mwait = 300*1000; | 361 | mwait = 300*1000; |
342 | } | 362 | } |
343 | max_wait_msecs -= mwait; | 363 | max_wait_msecs -= mwait; |
344 | msleep (mwait); | 364 | msleep(mwait); |
345 | } | 365 | } |
346 | 366 | ||
347 | printk(KERN_WARNING "EEH: Timed out waiting for slot status\n"); | 367 | printk(KERN_WARNING "EEH: Timed out waiting for slot status\n"); |
@@ -349,8 +369,11 @@ eeh_wait_for_slot_status(struct pci_dn *pdn, int max_wait_msecs) | |||
349 | } | 369 | } |
350 | 370 | ||
351 | /** | 371 | /** |
352 | * eeh_token_to_phys - convert EEH address token to phys address | 372 | * eeh_token_to_phys - Convert EEH address token to phys address |
353 | * @token i/o token, should be address in the form 0xA.... | 373 | * @token: I/O token, should be address in the form 0xA.... |
374 | * | ||
375 | * This routine should be called to convert virtual I/O address | ||
376 | * to physical one. | ||
354 | */ | 377 | */ |
355 | static inline unsigned long eeh_token_to_phys(unsigned long token) | 378 | static inline unsigned long eeh_token_to_phys(unsigned long token) |
356 | { | 379 | { |
@@ -365,8 +388,11 @@ static inline unsigned long eeh_token_to_phys(unsigned long token) | |||
365 | return pa | (token & (PAGE_SIZE-1)); | 388 | return pa | (token & (PAGE_SIZE-1)); |
366 | } | 389 | } |
367 | 390 | ||
368 | /** | 391 | /** |
369 | * Return the "partitionable endpoint" (pe) under which this device lies | 392 | * find_device_pe - Retrieve the PE for the given device |
393 | * @dn: device node | ||
394 | * | ||
395 | * Return the PE under which this device lies | ||
370 | */ | 396 | */ |
371 | struct device_node * find_device_pe(struct device_node *dn) | 397 | struct device_node * find_device_pe(struct device_node *dn) |
372 | { | 398 | { |
@@ -377,14 +403,18 @@ struct device_node * find_device_pe(struct device_node *dn) | |||
377 | return dn; | 403 | return dn; |
378 | } | 404 | } |
379 | 405 | ||
380 | /** Mark all devices that are children of this device as failed. | 406 | /** |
381 | * Mark the device driver too, so that it can see the failure | 407 | * __eeh_mark_slot - Mark all child devices as failed |
382 | * immediately; this is critical, since some drivers poll | 408 | * @parent: parent device |
383 | * status registers in interrupts ... If a driver is polling, | 409 | * @mode_flag: failure flag |
384 | * and the slot is frozen, then the driver can deadlock in | 410 | * |
385 | * an interrupt context, which is bad. | 411 | * Mark all devices that are children of this device as failed. |
412 | * Mark the device driver too, so that it can see the failure | ||
413 | * immediately; this is critical, since some drivers poll | ||
414 | * status registers in interrupts ... If a driver is polling, | ||
415 | * and the slot is frozen, then the driver can deadlock in | ||
416 | * an interrupt context, which is bad. | ||
386 | */ | 417 | */ |
387 | |||
388 | static void __eeh_mark_slot(struct device_node *parent, int mode_flag) | 418 | static void __eeh_mark_slot(struct device_node *parent, int mode_flag) |
389 | { | 419 | { |
390 | struct device_node *dn; | 420 | struct device_node *dn; |
@@ -404,10 +434,18 @@ static void __eeh_mark_slot(struct device_node *parent, int mode_flag) | |||
404 | } | 434 | } |
405 | } | 435 | } |
406 | 436 | ||
407 | void eeh_mark_slot (struct device_node *dn, int mode_flag) | 437 | /** |
438 | * eeh_mark_slot - Mark the indicated device and its children as failed | ||
439 | * @dn: parent device | ||
440 | * @mode_flag: failure flag | ||
441 | * | ||
442 | * Mark the indicated device and its child devices as failed. | ||
443 | * The device drivers are marked as failed as well. | ||
444 | */ | ||
445 | void eeh_mark_slot(struct device_node *dn, int mode_flag) | ||
408 | { | 446 | { |
409 | struct pci_dev *dev; | 447 | struct pci_dev *dev; |
410 | dn = find_device_pe (dn); | 448 | dn = find_device_pe(dn); |
411 | 449 | ||
412 | /* Back up one, since config addrs might be shared */ | 450 | /* Back up one, since config addrs might be shared */ |
413 | if (!pcibios_find_pci_bus(dn) && PCI_DN(dn->parent)) | 451 | if (!pcibios_find_pci_bus(dn) && PCI_DN(dn->parent)) |
@@ -423,6 +461,13 @@ void eeh_mark_slot (struct device_node *dn, int mode_flag) | |||
423 | __eeh_mark_slot(dn, mode_flag); | 461 | __eeh_mark_slot(dn, mode_flag); |
424 | } | 462 | } |
425 | 463 | ||
464 | /** | ||
465 | * __eeh_clear_slot - Clear failure flag for the child devices | ||
466 | * @parent: parent device | ||
467 | * @mode_flag: flag to be cleared | ||
468 | * | ||
469 | * Clear failure flag for the child devices. | ||
470 | */ | ||
426 | static void __eeh_clear_slot(struct device_node *parent, int mode_flag) | 471 | static void __eeh_clear_slot(struct device_node *parent, int mode_flag) |
427 | { | 472 | { |
428 | struct device_node *dn; | 473 | struct device_node *dn; |
@@ -436,12 +481,19 @@ static void __eeh_clear_slot(struct device_node *parent, int mode_flag) | |||
436 | } | 481 | } |
437 | } | 482 | } |
438 | 483 | ||
439 | void eeh_clear_slot (struct device_node *dn, int mode_flag) | 484 | /** |
485 | * eeh_clear_slot - Clear failure flag for the indicated device and its children | ||
486 | * @dn: parent device | ||
487 | * @mode_flag: flag to be cleared | ||
488 | * | ||
489 | * Clear failure flag for the indicated device and its children. | ||
490 | */ | ||
491 | void eeh_clear_slot(struct device_node *dn, int mode_flag) | ||
440 | { | 492 | { |
441 | unsigned long flags; | 493 | unsigned long flags; |
442 | raw_spin_lock_irqsave(&confirm_error_lock, flags); | 494 | raw_spin_lock_irqsave(&confirm_error_lock, flags); |
443 | 495 | ||
444 | dn = find_device_pe (dn); | 496 | dn = find_device_pe(dn); |
445 | 497 | ||
446 | /* Back up one, since config addrs might be shared */ | 498 | /* Back up one, since config addrs might be shared */ |
447 | if (!pcibios_find_pci_bus(dn) && PCI_DN(dn->parent)) | 499 | if (!pcibios_find_pci_bus(dn) && PCI_DN(dn->parent)) |
@@ -453,43 +505,10 @@ void eeh_clear_slot (struct device_node *dn, int mode_flag) | |||
453 | raw_spin_unlock_irqrestore(&confirm_error_lock, flags); | 505 | raw_spin_unlock_irqrestore(&confirm_error_lock, flags); |
454 | } | 506 | } |
455 | 507 | ||
456 | void __eeh_set_pe_freset(struct device_node *parent, unsigned int *freset) | ||
457 | { | ||
458 | struct device_node *dn; | ||
459 | |||
460 | for_each_child_of_node(parent, dn) { | ||
461 | if (PCI_DN(dn)) { | ||
462 | |||
463 | struct pci_dev *dev = PCI_DN(dn)->pcidev; | ||
464 | |||
465 | if (dev && dev->driver) | ||
466 | *freset |= dev->needs_freset; | ||
467 | |||
468 | __eeh_set_pe_freset(dn, freset); | ||
469 | } | ||
470 | } | ||
471 | } | ||
472 | |||
473 | void eeh_set_pe_freset(struct device_node *dn, unsigned int *freset) | ||
474 | { | ||
475 | struct pci_dev *dev; | ||
476 | dn = find_device_pe(dn); | ||
477 | |||
478 | /* Back up one, since config addrs might be shared */ | ||
479 | if (!pcibios_find_pci_bus(dn) && PCI_DN(dn->parent)) | ||
480 | dn = dn->parent; | ||
481 | |||
482 | dev = PCI_DN(dn)->pcidev; | ||
483 | if (dev) | ||
484 | *freset |= dev->needs_freset; | ||
485 | |||
486 | __eeh_set_pe_freset(dn, freset); | ||
487 | } | ||
488 | |||
489 | /** | 508 | /** |
490 | * eeh_dn_check_failure - check if all 1's data is due to EEH slot freeze | 509 | * eeh_dn_check_failure - Check if all 1's data is due to EEH slot freeze |
491 | * @dn device node | 510 | * @dn: device node |
492 | * @dev pci device, if known | 511 | * @dev: pci device, if known |
493 | * | 512 | * |
494 | * Check for an EEH failure for the given device node. Call this | 513 | * Check for an EEH failure for the given device node. Call this |
495 | * routine if the result of a read was all 0xff's and you want to | 514 | * routine if the result of a read was all 0xff's and you want to |
@@ -548,11 +567,11 @@ int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev) | |||
548 | pdn->eeh_check_count ++; | 567 | pdn->eeh_check_count ++; |
549 | if (pdn->eeh_check_count % EEH_MAX_FAILS == 0) { | 568 | if (pdn->eeh_check_count % EEH_MAX_FAILS == 0) { |
550 | location = of_get_property(dn, "ibm,loc-code", NULL); | 569 | location = of_get_property(dn, "ibm,loc-code", NULL); |
551 | printk (KERN_ERR "EEH: %d reads ignored for recovering device at " | 570 | printk(KERN_ERR "EEH: %d reads ignored for recovering device at " |
552 | "location=%s driver=%s pci addr=%s\n", | 571 | "location=%s driver=%s pci addr=%s\n", |
553 | pdn->eeh_check_count, location, | 572 | pdn->eeh_check_count, location, |
554 | eeh_driver_name(dev), eeh_pci_name(dev)); | 573 | eeh_driver_name(dev), eeh_pci_name(dev)); |
555 | printk (KERN_ERR "EEH: Might be infinite loop in %s driver\n", | 574 | printk(KERN_ERR "EEH: Might be infinite loop in %s driver\n", |
556 | eeh_driver_name(dev)); | 575 | eeh_driver_name(dev)); |
557 | dump_stack(); | 576 | dump_stack(); |
558 | } | 577 | } |
@@ -579,7 +598,8 @@ int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev) | |||
579 | } | 598 | } |
580 | 599 | ||
581 | /* Note that config-io to empty slots may fail; | 600 | /* Note that config-io to empty slots may fail; |
582 | * they are empty when they don't have children. */ | 601 | * they are empty when they don't have children. |
602 | */ | ||
583 | if ((rets[0] == 5) && (rets[2] == 0) && (dn->child == NULL)) { | 603 | if ((rets[0] == 5) && (rets[2] == 0) && (dn->child == NULL)) { |
584 | false_positives++; | 604 | false_positives++; |
585 | pdn->eeh_false_positives ++; | 605 | pdn->eeh_false_positives ++; |
@@ -609,15 +629,17 @@ int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev) | |||
609 | 629 | ||
610 | /* Avoid repeated reports of this failure, including problems | 630 | /* Avoid repeated reports of this failure, including problems |
611 | * with other functions on this device, and functions under | 631 | * with other functions on this device, and functions under |
612 | * bridges. */ | 632 | * bridges. |
613 | eeh_mark_slot (dn, EEH_MODE_ISOLATED); | 633 | */ |
634 | eeh_mark_slot(dn, EEH_MODE_ISOLATED); | ||
614 | raw_spin_unlock_irqrestore(&confirm_error_lock, flags); | 635 | raw_spin_unlock_irqrestore(&confirm_error_lock, flags); |
615 | 636 | ||
616 | eeh_send_failure_event (dn, dev); | 637 | eeh_send_failure_event(dn, dev); |
617 | 638 | ||
618 | /* Most EEH events are due to device driver bugs. Having | 639 | /* Most EEH events are due to device driver bugs. Having |
619 | * a stack trace will help the device-driver authors figure | 640 | * a stack trace will help the device-driver authors figure |
620 | * out what happened. So print that out. */ | 641 | * out what happened. So print that out. |
642 | */ | ||
621 | dump_stack(); | 643 | dump_stack(); |
622 | return 1; | 644 | return 1; |
623 | 645 | ||
@@ -629,9 +651,9 @@ dn_unlock: | |||
629 | EXPORT_SYMBOL_GPL(eeh_dn_check_failure); | 651 | EXPORT_SYMBOL_GPL(eeh_dn_check_failure); |
630 | 652 | ||
631 | /** | 653 | /** |
632 | * eeh_check_failure - check if all 1's data is due to EEH slot freeze | 654 | * eeh_check_failure - Check if all 1's data is due to EEH slot freeze |
633 | * @token i/o token, should be address in the form 0xA.... | 655 | * @token: I/O token, should be address in the form 0xA.... |
634 | * @val value, should be all 1's (XXX why do we need this arg??) | 656 | * @val: value, should be all 1's (XXX why do we need this arg??) |
635 | * | 657 | * |
636 | * Check for an EEH failure at the given token address. Call this | 658 | * Check for an EEH failure at the given token address. Call this |
637 | * routine if the result of a read was all 0xff's and you want to | 659 | * routine if the result of a read was all 0xff's and you want to |
@@ -655,7 +677,7 @@ unsigned long eeh_check_failure(const volatile void __iomem *token, unsigned lon | |||
655 | } | 677 | } |
656 | 678 | ||
657 | dn = pci_device_to_OF_node(dev); | 679 | dn = pci_device_to_OF_node(dev); |
658 | eeh_dn_check_failure (dn, dev); | 680 | eeh_dn_check_failure(dn, dev); |
659 | 681 | ||
660 | pci_dev_put(dev); | 682 | pci_dev_put(dev); |
661 | return val; | 683 | return val; |
@@ -663,14 +685,15 @@ unsigned long eeh_check_failure(const volatile void __iomem *token, unsigned lon | |||
663 | 685 | ||
664 | EXPORT_SYMBOL(eeh_check_failure); | 686 | EXPORT_SYMBOL(eeh_check_failure); |
665 | 687 | ||
666 | /* ------------------------------------------------------------- */ | ||
667 | /* The code below deals with error recovery */ | ||
668 | 688 | ||
669 | /** | 689 | /** |
670 | * rtas_pci_enable - enable MMIO or DMA transfers for this slot | 690 | * rtas_pci_enable - Enable MMIO or DMA transfers for this slot |
671 | * @pdn pci device node | 691 | * @pdn pci device node |
692 | * | ||
693 | * This routine should be called to reenable frozen MMIO or DMA | ||
694 | * so that it would work correctly again. It's useful while doing | ||
695 | * recovery or log collection on the indicated device. | ||
672 | */ | 696 | */ |
673 | |||
674 | int | 697 | int |
675 | rtas_pci_enable(struct pci_dn *pdn, int function) | 698 | rtas_pci_enable(struct pci_dn *pdn, int function) |
676 | { | 699 | { |
@@ -692,7 +715,7 @@ rtas_pci_enable(struct pci_dn *pdn, int function) | |||
692 | printk(KERN_WARNING "EEH: Unexpected state change %d, err=%d dn=%s\n", | 715 | printk(KERN_WARNING "EEH: Unexpected state change %d, err=%d dn=%s\n", |
693 | function, rc, pdn->node->full_name); | 716 | function, rc, pdn->node->full_name); |
694 | 717 | ||
695 | rc = eeh_wait_for_slot_status (pdn, PCI_BUS_RESET_WAIT_MSEC); | 718 | rc = eeh_wait_for_slot_status(pdn, PCI_BUS_RESET_WAIT_MSEC); |
696 | if ((rc == 4) && (function == EEH_THAW_MMIO)) | 719 | if ((rc == 4) && (function == EEH_THAW_MMIO)) |
697 | return 0; | 720 | return 0; |
698 | 721 | ||
@@ -700,27 +723,25 @@ rtas_pci_enable(struct pci_dn *pdn, int function) | |||
700 | } | 723 | } |
701 | 724 | ||
702 | /** | 725 | /** |
703 | * rtas_pci_slot_reset - raises/lowers the pci #RST line | 726 | * rtas_pci_slot_reset - Raises/Lowers the pci #RST line |
704 | * @pdn pci device node | 727 | * @pdn: pci device node |
705 | * @state: 1/0 to raise/lower the #RST | 728 | * @state: 1/0 to raise/lower the #RST |
706 | * | 729 | * |
707 | * Clear the EEH-frozen condition on a slot. This routine | 730 | * Clear the EEH-frozen condition on a slot. This routine |
708 | * asserts the PCI #RST line if the 'state' argument is '1', | 731 | * asserts the PCI #RST line if the 'state' argument is '1', |
709 | * and drops the #RST line if 'state is '0'. This routine is | 732 | * and drops the #RST line if 'state is '0'. This routine is |
710 | * safe to call in an interrupt context. | 733 | * safe to call in an interrupt context. |
711 | * | ||
712 | */ | 734 | */ |
713 | |||
714 | static void | 735 | static void |
715 | rtas_pci_slot_reset(struct pci_dn *pdn, int state) | 736 | rtas_pci_slot_reset(struct pci_dn *pdn, int state) |
716 | { | 737 | { |
717 | int config_addr; | 738 | int config_addr; |
718 | int rc; | 739 | int rc; |
719 | 740 | ||
720 | BUG_ON (pdn==NULL); | 741 | BUG_ON(pdn==NULL); |
721 | 742 | ||
722 | if (!pdn->phb) { | 743 | if (!pdn->phb) { |
723 | printk (KERN_WARNING "EEH: in slot reset, device node %s has no phb\n", | 744 | printk(KERN_WARNING "EEH: in slot reset, device node %s has no phb\n", |
724 | pdn->node->full_name); | 745 | pdn->node->full_name); |
725 | return; | 746 | return; |
726 | } | 747 | } |
@@ -752,12 +773,12 @@ rtas_pci_slot_reset(struct pci_dn *pdn, int state) | |||
752 | 773 | ||
753 | /** | 774 | /** |
754 | * pcibios_set_pcie_slot_reset - Set PCI-E reset state | 775 | * pcibios_set_pcie_slot_reset - Set PCI-E reset state |
755 | * @dev: pci device struct | 776 | * @dev: pci device struct |
756 | * @state: reset state to enter | 777 | * @state: reset state to enter |
757 | * | 778 | * |
758 | * Return value: | 779 | * Return value: |
759 | * 0 if success | 780 | * 0 if success |
760 | **/ | 781 | */ |
761 | int pcibios_set_pcie_reset_state(struct pci_dev *dev, enum pcie_reset_state state) | 782 | int pcibios_set_pcie_reset_state(struct pci_dev *dev, enum pcie_reset_state state) |
762 | { | 783 | { |
763 | struct device_node *dn = pci_device_to_OF_node(dev); | 784 | struct device_node *dn = pci_device_to_OF_node(dev); |
@@ -781,10 +802,62 @@ int pcibios_set_pcie_reset_state(struct pci_dev *dev, enum pcie_reset_state stat | |||
781 | } | 802 | } |
782 | 803 | ||
783 | /** | 804 | /** |
784 | * rtas_set_slot_reset -- assert the pci #RST line for 1/4 second | 805 | * __eeh_set_pe_freset - Check the required reset for child devices |
785 | * @pdn: pci device node to be reset. | 806 | * @parent: parent device |
807 | * @freset: return value | ||
808 | * | ||
809 | * Each device might have its preferred reset type: fundamental or | ||
810 | * hot reset. The routine is used to collect the information from | ||
811 | * the child devices so that they could be reset accordingly. | ||
786 | */ | 812 | */ |
813 | void __eeh_set_pe_freset(struct device_node *parent, unsigned int *freset) | ||
814 | { | ||
815 | struct device_node *dn; | ||
816 | |||
817 | for_each_child_of_node(parent, dn) { | ||
818 | if (PCI_DN(dn)) { | ||
819 | struct pci_dev *dev = PCI_DN(dn)->pcidev; | ||
820 | |||
821 | if (dev && dev->driver) | ||
822 | *freset |= dev->needs_freset; | ||
823 | |||
824 | __eeh_set_pe_freset(dn, freset); | ||
825 | } | ||
826 | } | ||
827 | } | ||
828 | |||
829 | /** | ||
830 | * eeh_set_pe_freset - Check the required reset for the indicated device and its children | ||
831 | * @dn: parent device | ||
832 | * @freset: return value | ||
833 | * | ||
834 | * Each device might have its preferred reset type: fundamental or | ||
835 | * hot reset. The routine is used to collected the information for | ||
836 | * the indicated device and its children so that the bunch of the | ||
837 | * devices could be reset properly. | ||
838 | */ | ||
839 | void eeh_set_pe_freset(struct device_node *dn, unsigned int *freset) | ||
840 | { | ||
841 | struct pci_dev *dev; | ||
842 | dn = find_device_pe(dn); | ||
843 | |||
844 | /* Back up one, since config addrs might be shared */ | ||
845 | if (!pcibios_find_pci_bus(dn) && PCI_DN(dn->parent)) | ||
846 | dn = dn->parent; | ||
787 | 847 | ||
848 | dev = PCI_DN(dn)->pcidev; | ||
849 | if (dev) | ||
850 | *freset |= dev->needs_freset; | ||
851 | |||
852 | __eeh_set_pe_freset(dn, freset); | ||
853 | } | ||
854 | |||
855 | /** | ||
856 | * __rtas_set_slot_reset - Assert the pci #RST line for 1/4 second | ||
857 | * @pdn: pci device node to be reset. | ||
858 | * | ||
859 | * Assert the PCI #RST line for 1/4 second. | ||
860 | */ | ||
788 | static void __rtas_set_slot_reset(struct pci_dn *pdn) | 861 | static void __rtas_set_slot_reset(struct pci_dn *pdn) |
789 | { | 862 | { |
790 | unsigned int freset = 0; | 863 | unsigned int freset = 0; |
@@ -803,25 +876,35 @@ static void __rtas_set_slot_reset(struct pci_dn *pdn) | |||
803 | rtas_pci_slot_reset(pdn, 1); | 876 | rtas_pci_slot_reset(pdn, 1); |
804 | 877 | ||
805 | /* The PCI bus requires that the reset be held high for at least | 878 | /* The PCI bus requires that the reset be held high for at least |
806 | * a 100 milliseconds. We wait a bit longer 'just in case'. */ | 879 | * a 100 milliseconds. We wait a bit longer 'just in case'. |
807 | 880 | */ | |
808 | #define PCI_BUS_RST_HOLD_TIME_MSEC 250 | 881 | #define PCI_BUS_RST_HOLD_TIME_MSEC 250 |
809 | msleep (PCI_BUS_RST_HOLD_TIME_MSEC); | 882 | msleep(PCI_BUS_RST_HOLD_TIME_MSEC); |
810 | 883 | ||
811 | /* We might get hit with another EEH freeze as soon as the | 884 | /* We might get hit with another EEH freeze as soon as the |
812 | * pci slot reset line is dropped. Make sure we don't miss | 885 | * pci slot reset line is dropped. Make sure we don't miss |
813 | * these, and clear the flag now. */ | 886 | * these, and clear the flag now. |
814 | eeh_clear_slot (pdn->node, EEH_MODE_ISOLATED); | 887 | */ |
888 | eeh_clear_slot(pdn->node, EEH_MODE_ISOLATED); | ||
815 | 889 | ||
816 | rtas_pci_slot_reset (pdn, 0); | 890 | rtas_pci_slot_reset(pdn, 0); |
817 | 891 | ||
818 | /* After a PCI slot has been reset, the PCI Express spec requires | 892 | /* After a PCI slot has been reset, the PCI Express spec requires |
819 | * a 1.5 second idle time for the bus to stabilize, before starting | 893 | * a 1.5 second idle time for the bus to stabilize, before starting |
820 | * up traffic. */ | 894 | * up traffic. |
895 | */ | ||
821 | #define PCI_BUS_SETTLE_TIME_MSEC 1800 | 896 | #define PCI_BUS_SETTLE_TIME_MSEC 1800 |
822 | msleep (PCI_BUS_SETTLE_TIME_MSEC); | 897 | msleep(PCI_BUS_SETTLE_TIME_MSEC); |
823 | } | 898 | } |
824 | 899 | ||
900 | /** | ||
901 | * rtas_set_slot_reset - Reset the indicated PE | ||
902 | * @pdn: PCI device node | ||
903 | * | ||
904 | * This routine should be called to reset indicated device, including | ||
905 | * PE. A PE might include multiple PCI devices and sometimes PCI bridges | ||
906 | * might be involved as well. | ||
907 | */ | ||
825 | int rtas_set_slot_reset(struct pci_dn *pdn) | 908 | int rtas_set_slot_reset(struct pci_dn *pdn) |
826 | { | 909 | { |
827 | int i, rc; | 910 | int i, rc; |
@@ -846,7 +929,6 @@ int rtas_set_slot_reset(struct pci_dn *pdn) | |||
846 | return -1; | 929 | return -1; |
847 | } | 930 | } |
848 | 931 | ||
849 | /* ------------------------------------------------------- */ | ||
850 | /** Save and restore of PCI BARs | 932 | /** Save and restore of PCI BARs |
851 | * | 933 | * |
852 | * Although firmware will set up BARs during boot, it doesn't | 934 | * Although firmware will set up BARs during boot, it doesn't |
@@ -863,7 +945,7 @@ int rtas_set_slot_reset(struct pci_dn *pdn) | |||
863 | * the expansion ROM base address, the latency timer, and etc. | 945 | * the expansion ROM base address, the latency timer, and etc. |
864 | * from the saved values in the device node. | 946 | * from the saved values in the device node. |
865 | */ | 947 | */ |
866 | static inline void __restore_bars (struct pci_dn *pdn) | 948 | static inline void __restore_bars(struct pci_dn *pdn) |
867 | { | 949 | { |
868 | int i; | 950 | int i; |
869 | u32 cmd; | 951 | u32 cmd; |
@@ -879,17 +961,18 @@ static inline void __restore_bars (struct pci_dn *pdn) | |||
879 | #define BYTE_SWAP(OFF) (8*((OFF)/4)+3-(OFF)) | 961 | #define BYTE_SWAP(OFF) (8*((OFF)/4)+3-(OFF)) |
880 | #define SAVED_BYTE(OFF) (((u8 *)(pdn->config_space))[BYTE_SWAP(OFF)]) | 962 | #define SAVED_BYTE(OFF) (((u8 *)(pdn->config_space))[BYTE_SWAP(OFF)]) |
881 | 963 | ||
882 | rtas_write_config (pdn, PCI_CACHE_LINE_SIZE, 1, | 964 | rtas_write_config(pdn, PCI_CACHE_LINE_SIZE, 1, |
883 | SAVED_BYTE(PCI_CACHE_LINE_SIZE)); | 965 | SAVED_BYTE(PCI_CACHE_LINE_SIZE)); |
884 | 966 | ||
885 | rtas_write_config (pdn, PCI_LATENCY_TIMER, 1, | 967 | rtas_write_config(pdn, PCI_LATENCY_TIMER, 1, |
886 | SAVED_BYTE(PCI_LATENCY_TIMER)); | 968 | SAVED_BYTE(PCI_LATENCY_TIMER)); |
887 | 969 | ||
888 | /* max latency, min grant, interrupt pin and line */ | 970 | /* max latency, min grant, interrupt pin and line */ |
889 | rtas_write_config(pdn, 15*4, 4, pdn->config_space[15]); | 971 | rtas_write_config(pdn, 15*4, 4, pdn->config_space[15]); |
890 | 972 | ||
891 | /* Restore PERR & SERR bits, some devices require it, | 973 | /* Restore PERR & SERR bits, some devices require it, |
892 | don't touch the other command bits */ | 974 | * don't touch the other command bits |
975 | */ | ||
893 | rtas_read_config(pdn, PCI_COMMAND, 4, &cmd); | 976 | rtas_read_config(pdn, PCI_COMMAND, 4, &cmd); |
894 | if (pdn->config_space[1] & PCI_COMMAND_PARITY) | 977 | if (pdn->config_space[1] & PCI_COMMAND_PARITY) |
895 | cmd |= PCI_COMMAND_PARITY; | 978 | cmd |= PCI_COMMAND_PARITY; |
@@ -903,7 +986,8 @@ static inline void __restore_bars (struct pci_dn *pdn) | |||
903 | } | 986 | } |
904 | 987 | ||
905 | /** | 988 | /** |
906 | * eeh_restore_bars - restore the PCI config space info | 989 | * eeh_restore_bars - Restore the PCI config space info |
990 | * @pdn: PCI device node | ||
907 | * | 991 | * |
908 | * This routine performs a recursive walk to the children | 992 | * This routine performs a recursive walk to the children |
909 | * of this device as well. | 993 | * of this device as well. |
@@ -915,14 +999,15 @@ void eeh_restore_bars(struct pci_dn *pdn) | |||
915 | return; | 999 | return; |
916 | 1000 | ||
917 | if ((pdn->eeh_mode & EEH_MODE_SUPPORTED) && !IS_BRIDGE(pdn->class_code)) | 1001 | if ((pdn->eeh_mode & EEH_MODE_SUPPORTED) && !IS_BRIDGE(pdn->class_code)) |
918 | __restore_bars (pdn); | 1002 | __restore_bars(pdn); |
919 | 1003 | ||
920 | for_each_child_of_node(pdn->node, dn) | 1004 | for_each_child_of_node(pdn->node, dn) |
921 | eeh_restore_bars (PCI_DN(dn)); | 1005 | eeh_restore_bars(PCI_DN(dn)); |
922 | } | 1006 | } |
923 | 1007 | ||
924 | /** | 1008 | /** |
925 | * eeh_save_bars - save device bars | 1009 | * eeh_save_bars - Save device bars |
1010 | * @pdn: PCI device node | ||
926 | * | 1011 | * |
927 | * Save the values of the device bars. Unlike the restore | 1012 | * Save the values of the device bars. Unlike the restore |
928 | * routine, this routine is *not* recursive. This is because | 1013 | * routine, this routine is *not* recursive. This is because |
@@ -940,6 +1025,14 @@ static void eeh_save_bars(struct pci_dn *pdn) | |||
940 | rtas_read_config(pdn, i * 4, 4, &pdn->config_space[i]); | 1025 | rtas_read_config(pdn, i * 4, 4, &pdn->config_space[i]); |
941 | } | 1026 | } |
942 | 1027 | ||
1028 | /** | ||
1029 | * rtas_configure_bridge - Configure PCI bridges for the indicated PE | ||
1030 | * @pdn: PCI device node | ||
1031 | * | ||
1032 | * PCI bridges might be included in PE. In order to make the PE work | ||
1033 | * again. The included PCI bridges should be recovered after the PE | ||
1034 | * encounters frozen state. | ||
1035 | */ | ||
943 | void | 1036 | void |
944 | rtas_configure_bridge(struct pci_dn *pdn) | 1037 | rtas_configure_bridge(struct pci_dn *pdn) |
945 | { | 1038 | { |
@@ -963,17 +1056,11 @@ rtas_configure_bridge(struct pci_dn *pdn) | |||
963 | BUID_HI(pdn->phb->buid), | 1056 | BUID_HI(pdn->phb->buid), |
964 | BUID_LO(pdn->phb->buid)); | 1057 | BUID_LO(pdn->phb->buid)); |
965 | if (rc) { | 1058 | if (rc) { |
966 | printk (KERN_WARNING "EEH: Unable to configure device bridge (%d) for %s\n", | 1059 | printk(KERN_WARNING "EEH: Unable to configure device bridge (%d) for %s\n", |
967 | rc, pdn->node->full_name); | 1060 | rc, pdn->node->full_name); |
968 | } | 1061 | } |
969 | } | 1062 | } |
970 | 1063 | ||
971 | /* ------------------------------------------------------------- */ | ||
972 | /* The code below deals with enabling EEH for devices during the | ||
973 | * early boot sequence. EEH must be enabled before any PCI probing | ||
974 | * can be done. | ||
975 | */ | ||
976 | |||
977 | #define EEH_ENABLE 1 | 1064 | #define EEH_ENABLE 1 |
978 | 1065 | ||
979 | struct eeh_early_enable_info { | 1066 | struct eeh_early_enable_info { |
@@ -981,7 +1068,18 @@ struct eeh_early_enable_info { | |||
981 | unsigned int buid_lo; | 1068 | unsigned int buid_lo; |
982 | }; | 1069 | }; |
983 | 1070 | ||
984 | static int get_pe_addr (int config_addr, | 1071 | /** |
1072 | * get_pe_addr - Retrieve PE address with given BDF address | ||
1073 | * @config_addr: BDF address | ||
1074 | * @info: BUID of the associated PHB | ||
1075 | * | ||
1076 | * There're 2 kinds of addresses existing in EEH core components: | ||
1077 | * BDF address and PE address. Besides, there has dedicated platform | ||
1078 | * dependent function call to retrieve the PE address according to | ||
1079 | * the given BDF address. Further more, we prefer PE address on BDF | ||
1080 | * address in EEH core components. | ||
1081 | */ | ||
1082 | static int get_pe_addr(int config_addr, | ||
985 | struct eeh_early_enable_info *info) | 1083 | struct eeh_early_enable_info *info) |
986 | { | 1084 | { |
987 | unsigned int rets[3]; | 1085 | unsigned int rets[3]; |
@@ -990,12 +1088,12 @@ static int get_pe_addr (int config_addr, | |||
990 | /* Use latest config-addr token on power6 */ | 1088 | /* Use latest config-addr token on power6 */ |
991 | if (ibm_get_config_addr_info2 != RTAS_UNKNOWN_SERVICE) { | 1089 | if (ibm_get_config_addr_info2 != RTAS_UNKNOWN_SERVICE) { |
992 | /* Make sure we have a PE in hand */ | 1090 | /* Make sure we have a PE in hand */ |
993 | ret = rtas_call (ibm_get_config_addr_info2, 4, 2, rets, | 1091 | ret = rtas_call(ibm_get_config_addr_info2, 4, 2, rets, |
994 | config_addr, info->buid_hi, info->buid_lo, 1); | 1092 | config_addr, info->buid_hi, info->buid_lo, 1); |
995 | if (ret || (rets[0]==0)) | 1093 | if (ret || (rets[0]==0)) |
996 | return 0; | 1094 | return 0; |
997 | 1095 | ||
998 | ret = rtas_call (ibm_get_config_addr_info2, 4, 2, rets, | 1096 | ret = rtas_call(ibm_get_config_addr_info2, 4, 2, rets, |
999 | config_addr, info->buid_hi, info->buid_lo, 0); | 1097 | config_addr, info->buid_hi, info->buid_lo, 0); |
1000 | if (ret) | 1098 | if (ret) |
1001 | return 0; | 1099 | return 0; |
@@ -1004,7 +1102,7 @@ static int get_pe_addr (int config_addr, | |||
1004 | 1102 | ||
1005 | /* Use older config-addr token on power5 */ | 1103 | /* Use older config-addr token on power5 */ |
1006 | if (ibm_get_config_addr_info != RTAS_UNKNOWN_SERVICE) { | 1104 | if (ibm_get_config_addr_info != RTAS_UNKNOWN_SERVICE) { |
1007 | ret = rtas_call (ibm_get_config_addr_info, 4, 2, rets, | 1105 | ret = rtas_call(ibm_get_config_addr_info, 4, 2, rets, |
1008 | config_addr, info->buid_hi, info->buid_lo, 0); | 1106 | config_addr, info->buid_hi, info->buid_lo, 0); |
1009 | if (ret) | 1107 | if (ret) |
1010 | return 0; | 1108 | return 0; |
@@ -1013,7 +1111,15 @@ static int get_pe_addr (int config_addr, | |||
1013 | return 0; | 1111 | return 0; |
1014 | } | 1112 | } |
1015 | 1113 | ||
1016 | /* Enable eeh for the given device node. */ | 1114 | /** |
1115 | * early_enable_eeh - Early enable EEH on the indicated device | ||
1116 | * @dn: device node | ||
1117 | * @data: BUID | ||
1118 | * | ||
1119 | * Enable EEH functionality on the specified PCI device. The function | ||
1120 | * is expected to be called before real PCI probing is done. However, | ||
1121 | * the PHBs have been initialized at this point. | ||
1122 | */ | ||
1017 | static void *early_enable_eeh(struct device_node *dn, void *data) | 1123 | static void *early_enable_eeh(struct device_node *dn, void *data) |
1018 | { | 1124 | { |
1019 | unsigned int rets[3]; | 1125 | unsigned int rets[3]; |
@@ -1047,7 +1153,8 @@ static void *early_enable_eeh(struct device_node *dn, void *data) | |||
1047 | pdn->class_code = *class_code; | 1153 | pdn->class_code = *class_code; |
1048 | 1154 | ||
1049 | /* Ok... see if this device supports EEH. Some do, some don't, | 1155 | /* Ok... see if this device supports EEH. Some do, some don't, |
1050 | * and the only way to find out is to check each and every one. */ | 1156 | * and the only way to find out is to check each and every one. |
1157 | */ | ||
1051 | regs = of_get_property(dn, "reg", NULL); | 1158 | regs = of_get_property(dn, "reg", NULL); |
1052 | if (regs) { | 1159 | if (regs) { |
1053 | /* First register entry is addr (00BBSS00) */ | 1160 | /* First register entry is addr (00BBSS00) */ |
@@ -1061,13 +1168,15 @@ static void *early_enable_eeh(struct device_node *dn, void *data) | |||
1061 | pdn->eeh_config_addr = regs[0]; | 1168 | pdn->eeh_config_addr = regs[0]; |
1062 | 1169 | ||
1063 | /* If the newer, better, ibm,get-config-addr-info is supported, | 1170 | /* If the newer, better, ibm,get-config-addr-info is supported, |
1064 | * then use that instead. */ | 1171 | * then use that instead. |
1172 | */ | ||
1065 | pdn->eeh_pe_config_addr = get_pe_addr(pdn->eeh_config_addr, info); | 1173 | pdn->eeh_pe_config_addr = get_pe_addr(pdn->eeh_config_addr, info); |
1066 | 1174 | ||
1067 | /* Some older systems (Power4) allow the | 1175 | /* Some older systems (Power4) allow the |
1068 | * ibm,set-eeh-option call to succeed even on nodes | 1176 | * ibm,set-eeh-option call to succeed even on nodes |
1069 | * where EEH is not supported. Verify support | 1177 | * where EEH is not supported. Verify support |
1070 | * explicitly. */ | 1178 | * explicitly. |
1179 | */ | ||
1071 | ret = read_slot_reset_state(pdn, rets); | 1180 | ret = read_slot_reset_state(pdn, rets); |
1072 | if ((ret == 0) && (rets[1] == 1)) | 1181 | if ((ret == 0) && (rets[1] == 1)) |
1073 | enable = 1; | 1182 | enable = 1; |
@@ -1083,7 +1192,8 @@ static void *early_enable_eeh(struct device_node *dn, void *data) | |||
1083 | } else { | 1192 | } else { |
1084 | 1193 | ||
1085 | /* This device doesn't support EEH, but it may have an | 1194 | /* This device doesn't support EEH, but it may have an |
1086 | * EEH parent, in which case we mark it as supported. */ | 1195 | * EEH parent, in which case we mark it as supported. |
1196 | */ | ||
1087 | if (dn->parent && PCI_DN(dn->parent) | 1197 | if (dn->parent && PCI_DN(dn->parent) |
1088 | && (PCI_DN(dn->parent)->eeh_mode & EEH_MODE_SUPPORTED)) { | 1198 | && (PCI_DN(dn->parent)->eeh_mode & EEH_MODE_SUPPORTED)) { |
1089 | /* Parent supports EEH. */ | 1199 | /* Parent supports EEH. */ |
@@ -1101,7 +1211,9 @@ static void *early_enable_eeh(struct device_node *dn, void *data) | |||
1101 | return NULL; | 1211 | return NULL; |
1102 | } | 1212 | } |
1103 | 1213 | ||
1104 | /* | 1214 | /** |
1215 | * eeh_init - EEH initialization | ||
1216 | * | ||
1105 | * Initialize EEH by trying to enable it for all of the adapters in the system. | 1217 | * Initialize EEH by trying to enable it for all of the adapters in the system. |
1106 | * As a side effect we can determine here if eeh is supported at all. | 1218 | * As a side effect we can determine here if eeh is supported at all. |
1107 | * Note that we leave EEH on so failed config cycles won't cause a machine | 1219 | * Note that we leave EEH on so failed config cycles won't cause a machine |
@@ -1133,7 +1245,7 @@ void __init eeh_init(void) | |||
1133 | ibm_slot_error_detail = rtas_token("ibm,slot-error-detail"); | 1245 | ibm_slot_error_detail = rtas_token("ibm,slot-error-detail"); |
1134 | ibm_get_config_addr_info = rtas_token("ibm,get-config-addr-info"); | 1246 | ibm_get_config_addr_info = rtas_token("ibm,get-config-addr-info"); |
1135 | ibm_get_config_addr_info2 = rtas_token("ibm,get-config-addr-info2"); | 1247 | ibm_get_config_addr_info2 = rtas_token("ibm,get-config-addr-info2"); |
1136 | ibm_configure_bridge = rtas_token ("ibm,configure-bridge"); | 1248 | ibm_configure_bridge = rtas_token("ibm,configure-bridge"); |
1137 | ibm_configure_pe = rtas_token("ibm,configure-pe"); | 1249 | ibm_configure_pe = rtas_token("ibm,configure-pe"); |
1138 | 1250 | ||
1139 | if (ibm_set_eeh_option == RTAS_UNKNOWN_SERVICE) | 1251 | if (ibm_set_eeh_option == RTAS_UNKNOWN_SERVICE) |
@@ -1170,7 +1282,7 @@ void __init eeh_init(void) | |||
1170 | } | 1282 | } |
1171 | 1283 | ||
1172 | /** | 1284 | /** |
1173 | * eeh_add_device_early - enable EEH for the indicated device_node | 1285 | * eeh_add_device_early - Enable EEH for the indicated device_node |
1174 | * @dn: device node for which to set up EEH | 1286 | * @dn: device node for which to set up EEH |
1175 | * | 1287 | * |
1176 | * This routine must be used to perform EEH initialization for PCI | 1288 | * This routine must be used to perform EEH initialization for PCI |
@@ -1199,6 +1311,14 @@ static void eeh_add_device_early(struct device_node *dn) | |||
1199 | early_enable_eeh(dn, &info); | 1311 | early_enable_eeh(dn, &info); |
1200 | } | 1312 | } |
1201 | 1313 | ||
1314 | /** | ||
1315 | * eeh_add_device_tree_early - Enable EEH for the indicated device | ||
1316 | * @dn: device node | ||
1317 | * | ||
1318 | * This routine must be used to perform EEH initialization for the | ||
1319 | * indicated PCI device that was added after system boot (e.g. | ||
1320 | * hotplug, dlpar). | ||
1321 | */ | ||
1202 | void eeh_add_device_tree_early(struct device_node *dn) | 1322 | void eeh_add_device_tree_early(struct device_node *dn) |
1203 | { | 1323 | { |
1204 | struct device_node *sib; | 1324 | struct device_node *sib; |
@@ -1210,7 +1330,7 @@ void eeh_add_device_tree_early(struct device_node *dn) | |||
1210 | EXPORT_SYMBOL_GPL(eeh_add_device_tree_early); | 1330 | EXPORT_SYMBOL_GPL(eeh_add_device_tree_early); |
1211 | 1331 | ||
1212 | /** | 1332 | /** |
1213 | * eeh_add_device_late - perform EEH initialization for the indicated pci device | 1333 | * eeh_add_device_late - Perform EEH initialization for the indicated pci device |
1214 | * @dev: pci device for which to set up EEH | 1334 | * @dev: pci device for which to set up EEH |
1215 | * | 1335 | * |
1216 | * This routine must be used to complete EEH initialization for PCI | 1336 | * This routine must be used to complete EEH initialization for PCI |
@@ -1234,13 +1354,21 @@ static void eeh_add_device_late(struct pci_dev *dev) | |||
1234 | } | 1354 | } |
1235 | WARN_ON(pdn->pcidev); | 1355 | WARN_ON(pdn->pcidev); |
1236 | 1356 | ||
1237 | pci_dev_get (dev); | 1357 | pci_dev_get(dev); |
1238 | pdn->pcidev = dev; | 1358 | pdn->pcidev = dev; |
1239 | 1359 | ||
1240 | pci_addr_cache_insert_device(dev); | 1360 | pci_addr_cache_insert_device(dev); |
1241 | eeh_sysfs_add_device(dev); | 1361 | eeh_sysfs_add_device(dev); |
1242 | } | 1362 | } |
1243 | 1363 | ||
1364 | /** | ||
1365 | * eeh_add_device_tree_late - Perform EEH initialization for the indicated PCI bus | ||
1366 | * @bus: PCI bus | ||
1367 | * | ||
1368 | * This routine must be used to perform EEH initialization for PCI | ||
1369 | * devices which are attached to the indicated PCI bus. The PCI bus | ||
1370 | * is added after system boot through hotplug or dlpar. | ||
1371 | */ | ||
1244 | void eeh_add_device_tree_late(struct pci_bus *bus) | 1372 | void eeh_add_device_tree_late(struct pci_bus *bus) |
1245 | { | 1373 | { |
1246 | struct pci_dev *dev; | 1374 | struct pci_dev *dev; |
@@ -1257,7 +1385,7 @@ void eeh_add_device_tree_late(struct pci_bus *bus) | |||
1257 | EXPORT_SYMBOL_GPL(eeh_add_device_tree_late); | 1385 | EXPORT_SYMBOL_GPL(eeh_add_device_tree_late); |
1258 | 1386 | ||
1259 | /** | 1387 | /** |
1260 | * eeh_remove_device - undo EEH setup for the indicated pci device | 1388 | * eeh_remove_device - Undo EEH setup for the indicated pci device |
1261 | * @dev: pci device to be removed | 1389 | * @dev: pci device to be removed |
1262 | * | 1390 | * |
1263 | * This routine should be called when a device is removed from | 1391 | * This routine should be called when a device is removed from |
@@ -1281,12 +1409,20 @@ static void eeh_remove_device(struct pci_dev *dev) | |||
1281 | return; | 1409 | return; |
1282 | } | 1410 | } |
1283 | PCI_DN(dn)->pcidev = NULL; | 1411 | PCI_DN(dn)->pcidev = NULL; |
1284 | pci_dev_put (dev); | 1412 | pci_dev_put(dev); |
1285 | 1413 | ||
1286 | pci_addr_cache_remove_device(dev); | 1414 | pci_addr_cache_remove_device(dev); |
1287 | eeh_sysfs_remove_device(dev); | 1415 | eeh_sysfs_remove_device(dev); |
1288 | } | 1416 | } |
1289 | 1417 | ||
1418 | /** | ||
1419 | * eeh_remove_bus_device - Undo EEH setup for the indicated PCI device | ||
1420 | * @dev: PCI device | ||
1421 | * | ||
1422 | * This routine must be called when a device is removed from the | ||
1423 | * running system through hotplug or dlpar. The corresponding | ||
1424 | * PCI address cache will be removed. | ||
1425 | */ | ||
1290 | void eeh_remove_bus_device(struct pci_dev *dev) | 1426 | void eeh_remove_bus_device(struct pci_dev *dev) |
1291 | { | 1427 | { |
1292 | struct pci_bus *bus = dev->subordinate; | 1428 | struct pci_bus *bus = dev->subordinate; |