diff options
Diffstat (limited to 'arch/powerpc/platforms/pseries/eeh.c')
-rw-r--r-- | arch/powerpc/platforms/pseries/eeh.c | 1044 |
1 files changed, 462 insertions, 582 deletions
diff --git a/arch/powerpc/platforms/pseries/eeh.c b/arch/powerpc/platforms/pseries/eeh.c index c0b40af4ce4..8011088392d 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> |
@@ -86,16 +86,8 @@ | |||
86 | /* Time to wait for a PCI slot to report status, in milliseconds */ | 86 | /* Time to wait for a PCI slot to report status, in milliseconds */ |
87 | #define PCI_BUS_RESET_WAIT_MSEC (60*1000) | 87 | #define PCI_BUS_RESET_WAIT_MSEC (60*1000) |
88 | 88 | ||
89 | /* RTAS tokens */ | 89 | /* Platform dependent EEH operations */ |
90 | static int ibm_set_eeh_option; | 90 | struct eeh_ops *eeh_ops = NULL; |
91 | static int ibm_set_slot_reset; | ||
92 | static int ibm_read_slot_reset_state; | ||
93 | static int ibm_read_slot_reset_state2; | ||
94 | static int ibm_slot_error_detail; | ||
95 | static int ibm_get_config_addr_info; | ||
96 | static int ibm_get_config_addr_info2; | ||
97 | static int ibm_configure_bridge; | ||
98 | static int ibm_configure_pe; | ||
99 | 91 | ||
100 | int eeh_subsystem_enabled; | 92 | int eeh_subsystem_enabled; |
101 | EXPORT_SYMBOL(eeh_subsystem_enabled); | 93 | EXPORT_SYMBOL(eeh_subsystem_enabled); |
@@ -103,14 +95,6 @@ EXPORT_SYMBOL(eeh_subsystem_enabled); | |||
103 | /* Lock to avoid races due to multiple reports of an error */ | 95 | /* Lock to avoid races due to multiple reports of an error */ |
104 | static DEFINE_RAW_SPINLOCK(confirm_error_lock); | 96 | static DEFINE_RAW_SPINLOCK(confirm_error_lock); |
105 | 97 | ||
106 | /* Buffer for reporting slot-error-detail rtas calls. Its here | ||
107 | * in BSS, and not dynamically alloced, so that it ends up in | ||
108 | * RMO where RTAS can access it. | ||
109 | */ | ||
110 | static unsigned char slot_errbuf[RTAS_ERROR_LOG_MAX]; | ||
111 | static DEFINE_SPINLOCK(slot_errbuf_lock); | ||
112 | static int eeh_error_buf_size; | ||
113 | |||
114 | /* Buffer for reporting pci register dumps. Its here in BSS, and | 98 | /* Buffer for reporting pci register dumps. Its here in BSS, and |
115 | * not dynamically alloced, so that it ends up in RMO where RTAS | 99 | * not dynamically alloced, so that it ends up in RMO where RTAS |
116 | * can access it. | 100 | * can access it. |
@@ -118,74 +102,50 @@ static int eeh_error_buf_size; | |||
118 | #define EEH_PCI_REGS_LOG_LEN 4096 | 102 | #define EEH_PCI_REGS_LOG_LEN 4096 |
119 | static unsigned char pci_regs_buf[EEH_PCI_REGS_LOG_LEN]; | 103 | static unsigned char pci_regs_buf[EEH_PCI_REGS_LOG_LEN]; |
120 | 104 | ||
121 | /* System monitoring statistics */ | 105 | /* |
122 | static unsigned long no_device; | 106 | * The struct is used to maintain the EEH global statistic |
123 | static unsigned long no_dn; | 107 | * information. Besides, the EEH global statistics will be |
124 | static unsigned long no_cfg_addr; | 108 | * exported to user space through procfs |
125 | static unsigned long ignored_check; | 109 | */ |
126 | static unsigned long total_mmio_ffs; | 110 | struct eeh_stats { |
127 | static unsigned long false_positives; | 111 | u64 no_device; /* PCI device not found */ |
128 | static unsigned long slot_resets; | 112 | u64 no_dn; /* OF node not found */ |
129 | 113 | u64 no_cfg_addr; /* Config address not found */ | |
130 | #define IS_BRIDGE(class_code) (((class_code)<<16) == PCI_BASE_CLASS_BRIDGE) | 114 | u64 ignored_check; /* EEH check skipped */ |
131 | 115 | u64 total_mmio_ffs; /* Total EEH checks */ | |
132 | /* --------------------------------------------------------------- */ | 116 | u64 false_positives; /* Unnecessary EEH checks */ |
133 | /* Below lies the EEH event infrastructure */ | 117 | u64 slot_resets; /* PE reset */ |
118 | }; | ||
134 | 119 | ||
135 | static void rtas_slot_error_detail(struct pci_dn *pdn, int severity, | 120 | static struct eeh_stats eeh_stats; |
136 | char *driver_log, size_t loglen) | ||
137 | { | ||
138 | int config_addr; | ||
139 | unsigned long flags; | ||
140 | int rc; | ||
141 | 121 | ||
142 | /* Log the error with the rtas logger */ | 122 | #define IS_BRIDGE(class_code) (((class_code)<<16) == PCI_BASE_CLASS_BRIDGE) |
143 | spin_lock_irqsave(&slot_errbuf_lock, flags); | ||
144 | memset(slot_errbuf, 0, eeh_error_buf_size); | ||
145 | |||
146 | /* Use PE configuration address, if present */ | ||
147 | config_addr = pdn->eeh_config_addr; | ||
148 | if (pdn->eeh_pe_config_addr) | ||
149 | config_addr = pdn->eeh_pe_config_addr; | ||
150 | |||
151 | rc = rtas_call(ibm_slot_error_detail, | ||
152 | 8, 1, NULL, config_addr, | ||
153 | BUID_HI(pdn->phb->buid), | ||
154 | BUID_LO(pdn->phb->buid), | ||
155 | virt_to_phys(driver_log), loglen, | ||
156 | virt_to_phys(slot_errbuf), | ||
157 | eeh_error_buf_size, | ||
158 | severity); | ||
159 | |||
160 | if (rc == 0) | ||
161 | log_error(slot_errbuf, ERR_TYPE_RTAS_LOG, 0); | ||
162 | spin_unlock_irqrestore(&slot_errbuf_lock, flags); | ||
163 | } | ||
164 | 123 | ||
165 | /** | 124 | /** |
166 | * gather_pci_data - copy assorted PCI config space registers to buff | 125 | * eeh_gather_pci_data - Copy assorted PCI config space registers to buff |
167 | * @pdn: device to report data for | 126 | * @edev: device to report data for |
168 | * @buf: point to buffer in which to log | 127 | * @buf: point to buffer in which to log |
169 | * @len: amount of room in buffer | 128 | * @len: amount of room in buffer |
170 | * | 129 | * |
171 | * This routine captures assorted PCI configuration space data, | 130 | * This routine captures assorted PCI configuration space data, |
172 | * and puts them into a buffer for RTAS error logging. | 131 | * and puts them into a buffer for RTAS error logging. |
173 | */ | 132 | */ |
174 | static size_t gather_pci_data(struct pci_dn *pdn, char * buf, size_t len) | 133 | static size_t eeh_gather_pci_data(struct eeh_dev *edev, char * buf, size_t len) |
175 | { | 134 | { |
176 | struct pci_dev *dev = pdn->pcidev; | 135 | struct device_node *dn = eeh_dev_to_of_node(edev); |
136 | struct pci_dev *dev = eeh_dev_to_pci_dev(edev); | ||
177 | u32 cfg; | 137 | u32 cfg; |
178 | int cap, i; | 138 | int cap, i; |
179 | int n = 0; | 139 | int n = 0; |
180 | 140 | ||
181 | n += scnprintf(buf+n, len-n, "%s\n", pdn->node->full_name); | 141 | n += scnprintf(buf+n, len-n, "%s\n", dn->full_name); |
182 | printk(KERN_WARNING "EEH: of node=%s\n", pdn->node->full_name); | 142 | printk(KERN_WARNING "EEH: of node=%s\n", dn->full_name); |
183 | 143 | ||
184 | rtas_read_config(pdn, PCI_VENDOR_ID, 4, &cfg); | 144 | eeh_ops->read_config(dn, PCI_VENDOR_ID, 4, &cfg); |
185 | n += scnprintf(buf+n, len-n, "dev/vend:%08x\n", cfg); | 145 | n += scnprintf(buf+n, len-n, "dev/vend:%08x\n", cfg); |
186 | printk(KERN_WARNING "EEH: PCI device/vendor: %08x\n", cfg); | 146 | printk(KERN_WARNING "EEH: PCI device/vendor: %08x\n", cfg); |
187 | 147 | ||
188 | rtas_read_config(pdn, PCI_COMMAND, 4, &cfg); | 148 | eeh_ops->read_config(dn, PCI_COMMAND, 4, &cfg); |
189 | n += scnprintf(buf+n, len-n, "cmd/stat:%x\n", cfg); | 149 | n += scnprintf(buf+n, len-n, "cmd/stat:%x\n", cfg); |
190 | printk(KERN_WARNING "EEH: PCI cmd/status register: %08x\n", cfg); | 150 | printk(KERN_WARNING "EEH: PCI cmd/status register: %08x\n", cfg); |
191 | 151 | ||
@@ -196,11 +156,11 @@ static size_t gather_pci_data(struct pci_dn *pdn, char * buf, size_t len) | |||
196 | 156 | ||
197 | /* Gather bridge-specific registers */ | 157 | /* Gather bridge-specific registers */ |
198 | if (dev->class >> 16 == PCI_BASE_CLASS_BRIDGE) { | 158 | if (dev->class >> 16 == PCI_BASE_CLASS_BRIDGE) { |
199 | rtas_read_config(pdn, PCI_SEC_STATUS, 2, &cfg); | 159 | eeh_ops->read_config(dn, PCI_SEC_STATUS, 2, &cfg); |
200 | n += scnprintf(buf+n, len-n, "sec stat:%x\n", cfg); | 160 | n += scnprintf(buf+n, len-n, "sec stat:%x\n", cfg); |
201 | printk(KERN_WARNING "EEH: Bridge secondary status: %04x\n", cfg); | 161 | printk(KERN_WARNING "EEH: Bridge secondary status: %04x\n", cfg); |
202 | 162 | ||
203 | rtas_read_config(pdn, PCI_BRIDGE_CONTROL, 2, &cfg); | 163 | eeh_ops->read_config(dn, PCI_BRIDGE_CONTROL, 2, &cfg); |
204 | n += scnprintf(buf+n, len-n, "brdg ctl:%x\n", cfg); | 164 | n += scnprintf(buf+n, len-n, "brdg ctl:%x\n", cfg); |
205 | printk(KERN_WARNING "EEH: Bridge control: %04x\n", cfg); | 165 | printk(KERN_WARNING "EEH: Bridge control: %04x\n", cfg); |
206 | } | 166 | } |
@@ -208,11 +168,11 @@ static size_t gather_pci_data(struct pci_dn *pdn, char * buf, size_t len) | |||
208 | /* Dump out the PCI-X command and status regs */ | 168 | /* Dump out the PCI-X command and status regs */ |
209 | cap = pci_find_capability(dev, PCI_CAP_ID_PCIX); | 169 | cap = pci_find_capability(dev, PCI_CAP_ID_PCIX); |
210 | if (cap) { | 170 | if (cap) { |
211 | rtas_read_config(pdn, cap, 4, &cfg); | 171 | eeh_ops->read_config(dn, cap, 4, &cfg); |
212 | n += scnprintf(buf+n, len-n, "pcix-cmd:%x\n", cfg); | 172 | n += scnprintf(buf+n, len-n, "pcix-cmd:%x\n", cfg); |
213 | printk(KERN_WARNING "EEH: PCI-X cmd: %08x\n", cfg); | 173 | printk(KERN_WARNING "EEH: PCI-X cmd: %08x\n", cfg); |
214 | 174 | ||
215 | rtas_read_config(pdn, cap+4, 4, &cfg); | 175 | eeh_ops->read_config(dn, cap+4, 4, &cfg); |
216 | n += scnprintf(buf+n, len-n, "pcix-stat:%x\n", cfg); | 176 | n += scnprintf(buf+n, len-n, "pcix-stat:%x\n", cfg); |
217 | printk(KERN_WARNING "EEH: PCI-X status: %08x\n", cfg); | 177 | printk(KERN_WARNING "EEH: PCI-X status: %08x\n", cfg); |
218 | } | 178 | } |
@@ -225,7 +185,7 @@ static size_t gather_pci_data(struct pci_dn *pdn, char * buf, size_t len) | |||
225 | "EEH: PCI-E capabilities and status follow:\n"); | 185 | "EEH: PCI-E capabilities and status follow:\n"); |
226 | 186 | ||
227 | for (i=0; i<=8; i++) { | 187 | for (i=0; i<=8; i++) { |
228 | rtas_read_config(pdn, cap+4*i, 4, &cfg); | 188 | eeh_ops->read_config(dn, cap+4*i, 4, &cfg); |
229 | n += scnprintf(buf+n, len-n, "%02x:%x\n", 4*i, cfg); | 189 | n += scnprintf(buf+n, len-n, "%02x:%x\n", 4*i, cfg); |
230 | printk(KERN_WARNING "EEH: PCI-E %02x: %08x\n", i, cfg); | 190 | printk(KERN_WARNING "EEH: PCI-E %02x: %08x\n", i, cfg); |
231 | } | 191 | } |
@@ -237,7 +197,7 @@ static size_t gather_pci_data(struct pci_dn *pdn, char * buf, size_t len) | |||
237 | "EEH: PCI-E AER capability register set follows:\n"); | 197 | "EEH: PCI-E AER capability register set follows:\n"); |
238 | 198 | ||
239 | for (i=0; i<14; i++) { | 199 | for (i=0; i<14; i++) { |
240 | rtas_read_config(pdn, cap+4*i, 4, &cfg); | 200 | eeh_ops->read_config(dn, cap+4*i, 4, &cfg); |
241 | n += scnprintf(buf+n, len-n, "%02x:%x\n", 4*i, cfg); | 201 | n += scnprintf(buf+n, len-n, "%02x:%x\n", 4*i, cfg); |
242 | printk(KERN_WARNING "EEH: PCI-E AER %02x: %08x\n", i, cfg); | 202 | printk(KERN_WARNING "EEH: PCI-E AER %02x: %08x\n", i, cfg); |
243 | } | 203 | } |
@@ -246,111 +206,46 @@ static size_t gather_pci_data(struct pci_dn *pdn, char * buf, size_t len) | |||
246 | 206 | ||
247 | /* Gather status on devices under the bridge */ | 207 | /* Gather status on devices under the bridge */ |
248 | if (dev->class >> 16 == PCI_BASE_CLASS_BRIDGE) { | 208 | if (dev->class >> 16 == PCI_BASE_CLASS_BRIDGE) { |
249 | struct device_node *dn; | 209 | struct device_node *child; |
250 | 210 | ||
251 | for_each_child_of_node(pdn->node, dn) { | 211 | for_each_child_of_node(dn, child) { |
252 | pdn = PCI_DN(dn); | 212 | if (of_node_to_eeh_dev(child)) |
253 | if (pdn) | 213 | n += eeh_gather_pci_data(of_node_to_eeh_dev(child), buf+n, len-n); |
254 | n += gather_pci_data(pdn, buf+n, len-n); | ||
255 | } | 214 | } |
256 | } | 215 | } |
257 | 216 | ||
258 | return n; | 217 | return n; |
259 | } | 218 | } |
260 | 219 | ||
261 | void eeh_slot_error_detail(struct pci_dn *pdn, int severity) | ||
262 | { | ||
263 | size_t loglen = 0; | ||
264 | pci_regs_buf[0] = 0; | ||
265 | |||
266 | rtas_pci_enable(pdn, EEH_THAW_MMIO); | ||
267 | rtas_configure_bridge(pdn); | ||
268 | eeh_restore_bars(pdn); | ||
269 | loglen = gather_pci_data(pdn, pci_regs_buf, EEH_PCI_REGS_LOG_LEN); | ||
270 | |||
271 | rtas_slot_error_detail(pdn, severity, pci_regs_buf, loglen); | ||
272 | } | ||
273 | |||
274 | /** | 220 | /** |
275 | * read_slot_reset_state - Read the reset state of a device node's slot | 221 | * eeh_slot_error_detail - Generate combined log including driver log and error log |
276 | * @dn: device node to read | 222 | * @edev: device to report error log for |
277 | * @rets: array to return results in | 223 | * @severity: temporary or permanent error log |
278 | */ | ||
279 | static int read_slot_reset_state(struct pci_dn *pdn, int rets[]) | ||
280 | { | ||
281 | int token, outputs; | ||
282 | int config_addr; | ||
283 | |||
284 | if (ibm_read_slot_reset_state2 != RTAS_UNKNOWN_SERVICE) { | ||
285 | token = ibm_read_slot_reset_state2; | ||
286 | outputs = 4; | ||
287 | } else { | ||
288 | token = ibm_read_slot_reset_state; | ||
289 | rets[2] = 0; /* fake PE Unavailable info */ | ||
290 | outputs = 3; | ||
291 | } | ||
292 | |||
293 | /* Use PE configuration address, if present */ | ||
294 | config_addr = pdn->eeh_config_addr; | ||
295 | if (pdn->eeh_pe_config_addr) | ||
296 | config_addr = pdn->eeh_pe_config_addr; | ||
297 | |||
298 | return rtas_call(token, 3, outputs, rets, config_addr, | ||
299 | BUID_HI(pdn->phb->buid), BUID_LO(pdn->phb->buid)); | ||
300 | } | ||
301 | |||
302 | /** | ||
303 | * eeh_wait_for_slot_status - returns error status of slot | ||
304 | * @pdn pci device node | ||
305 | * @max_wait_msecs maximum number to millisecs to wait | ||
306 | * | ||
307 | * Return negative value if a permanent error, else return | ||
308 | * Partition Endpoint (PE) status value. | ||
309 | * | 224 | * |
310 | * If @max_wait_msecs is positive, then this routine will | 225 | * This routine should be called to generate the combined log, which |
311 | * sleep until a valid status can be obtained, or until | 226 | * is comprised of driver log and error log. The driver log is figured |
312 | * the max allowed wait time is exceeded, in which case | 227 | * out from the config space of the corresponding PCI device, while |
313 | * a -2 is returned. | 228 | * the error log is fetched through platform dependent function call. |
314 | */ | 229 | */ |
315 | int | 230 | void eeh_slot_error_detail(struct eeh_dev *edev, int severity) |
316 | eeh_wait_for_slot_status(struct pci_dn *pdn, int max_wait_msecs) | ||
317 | { | 231 | { |
318 | int rc; | 232 | size_t loglen = 0; |
319 | int rets[3]; | 233 | pci_regs_buf[0] = 0; |
320 | int mwait; | ||
321 | |||
322 | while (1) { | ||
323 | rc = read_slot_reset_state(pdn, rets); | ||
324 | if (rc) return rc; | ||
325 | if (rets[1] == 0) return -1; /* EEH is not supported */ | ||
326 | |||
327 | if (rets[0] != 5) return rets[0]; /* return actual status */ | ||
328 | |||
329 | if (rets[2] == 0) return -1; /* permanently unavailable */ | ||
330 | 234 | ||
331 | if (max_wait_msecs <= 0) break; | 235 | eeh_pci_enable(edev, EEH_OPT_THAW_MMIO); |
236 | eeh_ops->configure_bridge(eeh_dev_to_of_node(edev)); | ||
237 | eeh_restore_bars(edev); | ||
238 | loglen = eeh_gather_pci_data(edev, pci_regs_buf, EEH_PCI_REGS_LOG_LEN); | ||
332 | 239 | ||
333 | mwait = rets[2]; | 240 | eeh_ops->get_log(eeh_dev_to_of_node(edev), severity, pci_regs_buf, loglen); |
334 | if (mwait <= 0) { | ||
335 | printk (KERN_WARNING | ||
336 | "EEH: Firmware returned bad wait value=%d\n", mwait); | ||
337 | mwait = 1000; | ||
338 | } else if (mwait > 300*1000) { | ||
339 | printk (KERN_WARNING | ||
340 | "EEH: Firmware is taking too long, time=%d\n", mwait); | ||
341 | mwait = 300*1000; | ||
342 | } | ||
343 | max_wait_msecs -= mwait; | ||
344 | msleep (mwait); | ||
345 | } | ||
346 | |||
347 | printk(KERN_WARNING "EEH: Timed out waiting for slot status\n"); | ||
348 | return -2; | ||
349 | } | 241 | } |
350 | 242 | ||
351 | /** | 243 | /** |
352 | * eeh_token_to_phys - convert EEH address token to phys address | 244 | * eeh_token_to_phys - Convert EEH address token to phys address |
353 | * @token i/o token, should be address in the form 0xA.... | 245 | * @token: I/O token, should be address in the form 0xA.... |
246 | * | ||
247 | * This routine should be called to convert virtual I/O address | ||
248 | * to physical one. | ||
354 | */ | 249 | */ |
355 | static inline unsigned long eeh_token_to_phys(unsigned long token) | 250 | static inline unsigned long eeh_token_to_phys(unsigned long token) |
356 | { | 251 | { |
@@ -365,36 +260,43 @@ static inline unsigned long eeh_token_to_phys(unsigned long token) | |||
365 | return pa | (token & (PAGE_SIZE-1)); | 260 | return pa | (token & (PAGE_SIZE-1)); |
366 | } | 261 | } |
367 | 262 | ||
368 | /** | 263 | /** |
369 | * Return the "partitionable endpoint" (pe) under which this device lies | 264 | * eeh_find_device_pe - Retrieve the PE for the given device |
265 | * @dn: device node | ||
266 | * | ||
267 | * Return the PE under which this device lies | ||
370 | */ | 268 | */ |
371 | struct device_node * find_device_pe(struct device_node *dn) | 269 | struct device_node *eeh_find_device_pe(struct device_node *dn) |
372 | { | 270 | { |
373 | while ((dn->parent) && PCI_DN(dn->parent) && | 271 | while (dn->parent && of_node_to_eeh_dev(dn->parent) && |
374 | (PCI_DN(dn->parent)->eeh_mode & EEH_MODE_SUPPORTED)) { | 272 | (of_node_to_eeh_dev(dn->parent)->mode & EEH_MODE_SUPPORTED)) { |
375 | dn = dn->parent; | 273 | dn = dn->parent; |
376 | } | 274 | } |
377 | return dn; | 275 | return dn; |
378 | } | 276 | } |
379 | 277 | ||
380 | /** Mark all devices that are children of this device as failed. | 278 | /** |
381 | * Mark the device driver too, so that it can see the failure | 279 | * __eeh_mark_slot - Mark all child devices as failed |
382 | * immediately; this is critical, since some drivers poll | 280 | * @parent: parent device |
383 | * status registers in interrupts ... If a driver is polling, | 281 | * @mode_flag: failure flag |
384 | * and the slot is frozen, then the driver can deadlock in | 282 | * |
385 | * an interrupt context, which is bad. | 283 | * Mark all devices that are children of this device as failed. |
284 | * Mark the device driver too, so that it can see the failure | ||
285 | * immediately; this is critical, since some drivers poll | ||
286 | * status registers in interrupts ... If a driver is polling, | ||
287 | * and the slot is frozen, then the driver can deadlock in | ||
288 | * an interrupt context, which is bad. | ||
386 | */ | 289 | */ |
387 | |||
388 | static void __eeh_mark_slot(struct device_node *parent, int mode_flag) | 290 | static void __eeh_mark_slot(struct device_node *parent, int mode_flag) |
389 | { | 291 | { |
390 | struct device_node *dn; | 292 | struct device_node *dn; |
391 | 293 | ||
392 | for_each_child_of_node(parent, dn) { | 294 | for_each_child_of_node(parent, dn) { |
393 | if (PCI_DN(dn)) { | 295 | if (of_node_to_eeh_dev(dn)) { |
394 | /* Mark the pci device driver too */ | 296 | /* Mark the pci device driver too */ |
395 | struct pci_dev *dev = PCI_DN(dn)->pcidev; | 297 | struct pci_dev *dev = of_node_to_eeh_dev(dn)->pdev; |
396 | 298 | ||
397 | PCI_DN(dn)->eeh_mode |= mode_flag; | 299 | of_node_to_eeh_dev(dn)->mode |= mode_flag; |
398 | 300 | ||
399 | if (dev && dev->driver) | 301 | if (dev && dev->driver) |
400 | dev->error_state = pci_channel_io_frozen; | 302 | dev->error_state = pci_channel_io_frozen; |
@@ -404,92 +306,81 @@ static void __eeh_mark_slot(struct device_node *parent, int mode_flag) | |||
404 | } | 306 | } |
405 | } | 307 | } |
406 | 308 | ||
407 | void eeh_mark_slot (struct device_node *dn, int mode_flag) | 309 | /** |
310 | * eeh_mark_slot - Mark the indicated device and its children as failed | ||
311 | * @dn: parent device | ||
312 | * @mode_flag: failure flag | ||
313 | * | ||
314 | * Mark the indicated device and its child devices as failed. | ||
315 | * The device drivers are marked as failed as well. | ||
316 | */ | ||
317 | void eeh_mark_slot(struct device_node *dn, int mode_flag) | ||
408 | { | 318 | { |
409 | struct pci_dev *dev; | 319 | struct pci_dev *dev; |
410 | dn = find_device_pe (dn); | 320 | dn = eeh_find_device_pe(dn); |
411 | 321 | ||
412 | /* Back up one, since config addrs might be shared */ | 322 | /* Back up one, since config addrs might be shared */ |
413 | if (!pcibios_find_pci_bus(dn) && PCI_DN(dn->parent)) | 323 | if (!pcibios_find_pci_bus(dn) && of_node_to_eeh_dev(dn->parent)) |
414 | dn = dn->parent; | 324 | dn = dn->parent; |
415 | 325 | ||
416 | PCI_DN(dn)->eeh_mode |= mode_flag; | 326 | of_node_to_eeh_dev(dn)->mode |= mode_flag; |
417 | 327 | ||
418 | /* Mark the pci device too */ | 328 | /* Mark the pci device too */ |
419 | dev = PCI_DN(dn)->pcidev; | 329 | dev = of_node_to_eeh_dev(dn)->pdev; |
420 | if (dev) | 330 | if (dev) |
421 | dev->error_state = pci_channel_io_frozen; | 331 | dev->error_state = pci_channel_io_frozen; |
422 | 332 | ||
423 | __eeh_mark_slot(dn, mode_flag); | 333 | __eeh_mark_slot(dn, mode_flag); |
424 | } | 334 | } |
425 | 335 | ||
336 | /** | ||
337 | * __eeh_clear_slot - Clear failure flag for the child devices | ||
338 | * @parent: parent device | ||
339 | * @mode_flag: flag to be cleared | ||
340 | * | ||
341 | * Clear failure flag for the child devices. | ||
342 | */ | ||
426 | static void __eeh_clear_slot(struct device_node *parent, int mode_flag) | 343 | static void __eeh_clear_slot(struct device_node *parent, int mode_flag) |
427 | { | 344 | { |
428 | struct device_node *dn; | 345 | struct device_node *dn; |
429 | 346 | ||
430 | for_each_child_of_node(parent, dn) { | 347 | for_each_child_of_node(parent, dn) { |
431 | if (PCI_DN(dn)) { | 348 | if (of_node_to_eeh_dev(dn)) { |
432 | PCI_DN(dn)->eeh_mode &= ~mode_flag; | 349 | of_node_to_eeh_dev(dn)->mode &= ~mode_flag; |
433 | PCI_DN(dn)->eeh_check_count = 0; | 350 | of_node_to_eeh_dev(dn)->check_count = 0; |
434 | __eeh_clear_slot(dn, mode_flag); | 351 | __eeh_clear_slot(dn, mode_flag); |
435 | } | 352 | } |
436 | } | 353 | } |
437 | } | 354 | } |
438 | 355 | ||
439 | void eeh_clear_slot (struct device_node *dn, int mode_flag) | 356 | /** |
357 | * eeh_clear_slot - Clear failure flag for the indicated device and its children | ||
358 | * @dn: parent device | ||
359 | * @mode_flag: flag to be cleared | ||
360 | * | ||
361 | * Clear failure flag for the indicated device and its children. | ||
362 | */ | ||
363 | void eeh_clear_slot(struct device_node *dn, int mode_flag) | ||
440 | { | 364 | { |
441 | unsigned long flags; | 365 | unsigned long flags; |
442 | raw_spin_lock_irqsave(&confirm_error_lock, flags); | 366 | raw_spin_lock_irqsave(&confirm_error_lock, flags); |
443 | 367 | ||
444 | dn = find_device_pe (dn); | 368 | dn = eeh_find_device_pe(dn); |
445 | 369 | ||
446 | /* Back up one, since config addrs might be shared */ | 370 | /* Back up one, since config addrs might be shared */ |
447 | if (!pcibios_find_pci_bus(dn) && PCI_DN(dn->parent)) | 371 | if (!pcibios_find_pci_bus(dn) && of_node_to_eeh_dev(dn->parent)) |
448 | dn = dn->parent; | 372 | dn = dn->parent; |
449 | 373 | ||
450 | PCI_DN(dn)->eeh_mode &= ~mode_flag; | 374 | of_node_to_eeh_dev(dn)->mode &= ~mode_flag; |
451 | PCI_DN(dn)->eeh_check_count = 0; | 375 | of_node_to_eeh_dev(dn)->check_count = 0; |
452 | __eeh_clear_slot(dn, mode_flag); | 376 | __eeh_clear_slot(dn, mode_flag); |
453 | raw_spin_unlock_irqrestore(&confirm_error_lock, flags); | 377 | raw_spin_unlock_irqrestore(&confirm_error_lock, flags); |
454 | } | 378 | } |
455 | 379 | ||
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 | /** | 380 | /** |
490 | * eeh_dn_check_failure - check if all 1's data is due to EEH slot freeze | 381 | * eeh_dn_check_failure - Check if all 1's data is due to EEH slot freeze |
491 | * @dn device node | 382 | * @dn: device node |
492 | * @dev pci device, if known | 383 | * @dev: pci device, if known |
493 | * | 384 | * |
494 | * Check for an EEH failure for the given device node. Call this | 385 | * 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 | 386 | * routine if the result of a read was all 0xff's and you want to |
@@ -504,35 +395,34 @@ void eeh_set_pe_freset(struct device_node *dn, unsigned int *freset) | |||
504 | int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev) | 395 | int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev) |
505 | { | 396 | { |
506 | int ret; | 397 | int ret; |
507 | int rets[3]; | ||
508 | unsigned long flags; | 398 | unsigned long flags; |
509 | struct pci_dn *pdn; | 399 | struct eeh_dev *edev; |
510 | int rc = 0; | 400 | int rc = 0; |
511 | const char *location; | 401 | const char *location; |
512 | 402 | ||
513 | total_mmio_ffs++; | 403 | eeh_stats.total_mmio_ffs++; |
514 | 404 | ||
515 | if (!eeh_subsystem_enabled) | 405 | if (!eeh_subsystem_enabled) |
516 | return 0; | 406 | return 0; |
517 | 407 | ||
518 | if (!dn) { | 408 | if (!dn) { |
519 | no_dn++; | 409 | eeh_stats.no_dn++; |
520 | return 0; | 410 | return 0; |
521 | } | 411 | } |
522 | dn = find_device_pe(dn); | 412 | dn = eeh_find_device_pe(dn); |
523 | pdn = PCI_DN(dn); | 413 | edev = of_node_to_eeh_dev(dn); |
524 | 414 | ||
525 | /* Access to IO BARs might get this far and still not want checking. */ | 415 | /* Access to IO BARs might get this far and still not want checking. */ |
526 | if (!(pdn->eeh_mode & EEH_MODE_SUPPORTED) || | 416 | if (!(edev->mode & EEH_MODE_SUPPORTED) || |
527 | pdn->eeh_mode & EEH_MODE_NOCHECK) { | 417 | edev->mode & EEH_MODE_NOCHECK) { |
528 | ignored_check++; | 418 | eeh_stats.ignored_check++; |
529 | pr_debug("EEH: Ignored check (%x) for %s %s\n", | 419 | pr_debug("EEH: Ignored check (%x) for %s %s\n", |
530 | pdn->eeh_mode, eeh_pci_name(dev), dn->full_name); | 420 | edev->mode, eeh_pci_name(dev), dn->full_name); |
531 | return 0; | 421 | return 0; |
532 | } | 422 | } |
533 | 423 | ||
534 | if (!pdn->eeh_config_addr && !pdn->eeh_pe_config_addr) { | 424 | if (!edev->config_addr && !edev->pe_config_addr) { |
535 | no_cfg_addr++; | 425 | eeh_stats.no_cfg_addr++; |
536 | return 0; | 426 | return 0; |
537 | } | 427 | } |
538 | 428 | ||
@@ -544,15 +434,15 @@ int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev) | |||
544 | */ | 434 | */ |
545 | raw_spin_lock_irqsave(&confirm_error_lock, flags); | 435 | raw_spin_lock_irqsave(&confirm_error_lock, flags); |
546 | rc = 1; | 436 | rc = 1; |
547 | if (pdn->eeh_mode & EEH_MODE_ISOLATED) { | 437 | if (edev->mode & EEH_MODE_ISOLATED) { |
548 | pdn->eeh_check_count ++; | 438 | edev->check_count++; |
549 | if (pdn->eeh_check_count % EEH_MAX_FAILS == 0) { | 439 | if (edev->check_count % EEH_MAX_FAILS == 0) { |
550 | location = of_get_property(dn, "ibm,loc-code", NULL); | 440 | location = of_get_property(dn, "ibm,loc-code", NULL); |
551 | printk (KERN_ERR "EEH: %d reads ignored for recovering device at " | 441 | printk(KERN_ERR "EEH: %d reads ignored for recovering device at " |
552 | "location=%s driver=%s pci addr=%s\n", | 442 | "location=%s driver=%s pci addr=%s\n", |
553 | pdn->eeh_check_count, location, | 443 | edev->check_count, location, |
554 | eeh_driver_name(dev), eeh_pci_name(dev)); | 444 | eeh_driver_name(dev), eeh_pci_name(dev)); |
555 | printk (KERN_ERR "EEH: Might be infinite loop in %s driver\n", | 445 | printk(KERN_ERR "EEH: Might be infinite loop in %s driver\n", |
556 | eeh_driver_name(dev)); | 446 | eeh_driver_name(dev)); |
557 | dump_stack(); | 447 | dump_stack(); |
558 | } | 448 | } |
@@ -566,58 +456,39 @@ int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev) | |||
566 | * function zero of a multi-function device. | 456 | * function zero of a multi-function device. |
567 | * In any case they must share a common PHB. | 457 | * In any case they must share a common PHB. |
568 | */ | 458 | */ |
569 | ret = read_slot_reset_state(pdn, rets); | 459 | ret = eeh_ops->get_state(dn, NULL); |
570 | |||
571 | /* If the call to firmware failed, punt */ | ||
572 | if (ret != 0) { | ||
573 | printk(KERN_WARNING "EEH: read_slot_reset_state() failed; rc=%d dn=%s\n", | ||
574 | ret, dn->full_name); | ||
575 | false_positives++; | ||
576 | pdn->eeh_false_positives ++; | ||
577 | rc = 0; | ||
578 | goto dn_unlock; | ||
579 | } | ||
580 | 460 | ||
581 | /* Note that config-io to empty slots may fail; | 461 | /* Note that config-io to empty slots may fail; |
582 | * they are empty when they don't have children. */ | 462 | * they are empty when they don't have children. |
583 | if ((rets[0] == 5) && (rets[2] == 0) && (dn->child == NULL)) { | 463 | * We will punt with the following conditions: Failure to get |
584 | false_positives++; | 464 | * PE's state, EEH not support and Permanently unavailable |
585 | pdn->eeh_false_positives ++; | 465 | * state, PE is in good state. |
586 | rc = 0; | 466 | */ |
587 | goto dn_unlock; | 467 | if ((ret < 0) || |
588 | } | 468 | (ret == EEH_STATE_NOT_SUPPORT) || |
589 | 469 | (ret & (EEH_STATE_MMIO_ACTIVE | EEH_STATE_DMA_ACTIVE)) == | |
590 | /* If EEH is not supported on this device, punt. */ | 470 | (EEH_STATE_MMIO_ACTIVE | EEH_STATE_DMA_ACTIVE)) { |
591 | if (rets[1] != 1) { | 471 | eeh_stats.false_positives++; |
592 | printk(KERN_WARNING "EEH: event on unsupported device, rc=%d dn=%s\n", | 472 | edev->false_positives ++; |
593 | ret, dn->full_name); | ||
594 | false_positives++; | ||
595 | pdn->eeh_false_positives ++; | ||
596 | rc = 0; | ||
597 | goto dn_unlock; | ||
598 | } | ||
599 | |||
600 | /* If not the kind of error we know about, punt. */ | ||
601 | if (rets[0] != 1 && rets[0] != 2 && rets[0] != 4 && rets[0] != 5) { | ||
602 | false_positives++; | ||
603 | pdn->eeh_false_positives ++; | ||
604 | rc = 0; | 473 | rc = 0; |
605 | goto dn_unlock; | 474 | goto dn_unlock; |
606 | } | 475 | } |
607 | 476 | ||
608 | slot_resets++; | 477 | eeh_stats.slot_resets++; |
609 | 478 | ||
610 | /* Avoid repeated reports of this failure, including problems | 479 | /* Avoid repeated reports of this failure, including problems |
611 | * with other functions on this device, and functions under | 480 | * with other functions on this device, and functions under |
612 | * bridges. */ | 481 | * bridges. |
613 | eeh_mark_slot (dn, EEH_MODE_ISOLATED); | 482 | */ |
483 | eeh_mark_slot(dn, EEH_MODE_ISOLATED); | ||
614 | raw_spin_unlock_irqrestore(&confirm_error_lock, flags); | 484 | raw_spin_unlock_irqrestore(&confirm_error_lock, flags); |
615 | 485 | ||
616 | eeh_send_failure_event (dn, dev); | 486 | eeh_send_failure_event(edev); |
617 | 487 | ||
618 | /* Most EEH events are due to device driver bugs. Having | 488 | /* Most EEH events are due to device driver bugs. Having |
619 | * a stack trace will help the device-driver authors figure | 489 | * a stack trace will help the device-driver authors figure |
620 | * out what happened. So print that out. */ | 490 | * out what happened. So print that out. |
491 | */ | ||
621 | dump_stack(); | 492 | dump_stack(); |
622 | return 1; | 493 | return 1; |
623 | 494 | ||
@@ -629,9 +500,9 @@ dn_unlock: | |||
629 | EXPORT_SYMBOL_GPL(eeh_dn_check_failure); | 500 | EXPORT_SYMBOL_GPL(eeh_dn_check_failure); |
630 | 501 | ||
631 | /** | 502 | /** |
632 | * eeh_check_failure - check if all 1's data is due to EEH slot freeze | 503 | * 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.... | 504 | * @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??) | 505 | * @val: value, should be all 1's (XXX why do we need this arg??) |
635 | * | 506 | * |
636 | * Check for an EEH failure at the given token address. Call this | 507 | * 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 | 508 | * routine if the result of a read was all 0xff's and you want to |
@@ -648,14 +519,14 @@ unsigned long eeh_check_failure(const volatile void __iomem *token, unsigned lon | |||
648 | 519 | ||
649 | /* Finding the phys addr + pci device; this is pretty quick. */ | 520 | /* Finding the phys addr + pci device; this is pretty quick. */ |
650 | addr = eeh_token_to_phys((unsigned long __force) token); | 521 | addr = eeh_token_to_phys((unsigned long __force) token); |
651 | dev = pci_get_device_by_addr(addr); | 522 | dev = pci_addr_cache_get_device(addr); |
652 | if (!dev) { | 523 | if (!dev) { |
653 | no_device++; | 524 | eeh_stats.no_device++; |
654 | return val; | 525 | return val; |
655 | } | 526 | } |
656 | 527 | ||
657 | dn = pci_device_to_OF_node(dev); | 528 | dn = pci_device_to_OF_node(dev); |
658 | eeh_dn_check_failure (dn, dev); | 529 | eeh_dn_check_failure(dn, dev); |
659 | 530 | ||
660 | pci_dev_put(dev); | 531 | pci_dev_put(dev); |
661 | return val; | 532 | return val; |
@@ -663,115 +534,54 @@ unsigned long eeh_check_failure(const volatile void __iomem *token, unsigned lon | |||
663 | 534 | ||
664 | EXPORT_SYMBOL(eeh_check_failure); | 535 | EXPORT_SYMBOL(eeh_check_failure); |
665 | 536 | ||
666 | /* ------------------------------------------------------------- */ | ||
667 | /* The code below deals with error recovery */ | ||
668 | 537 | ||
669 | /** | 538 | /** |
670 | * rtas_pci_enable - enable MMIO or DMA transfers for this slot | 539 | * eeh_pci_enable - Enable MMIO or DMA transfers for this slot |
671 | * @pdn pci device node | 540 | * @edev: pci device node |
541 | * | ||
542 | * This routine should be called to reenable frozen MMIO or DMA | ||
543 | * so that it would work correctly again. It's useful while doing | ||
544 | * recovery or log collection on the indicated device. | ||
672 | */ | 545 | */ |
673 | 546 | int eeh_pci_enable(struct eeh_dev *edev, int function) | |
674 | int | ||
675 | rtas_pci_enable(struct pci_dn *pdn, int function) | ||
676 | { | 547 | { |
677 | int config_addr; | ||
678 | int rc; | 548 | int rc; |
549 | struct device_node *dn = eeh_dev_to_of_node(edev); | ||
679 | 550 | ||
680 | /* Use PE configuration address, if present */ | 551 | rc = eeh_ops->set_option(dn, function); |
681 | config_addr = pdn->eeh_config_addr; | ||
682 | if (pdn->eeh_pe_config_addr) | ||
683 | config_addr = pdn->eeh_pe_config_addr; | ||
684 | |||
685 | rc = rtas_call(ibm_set_eeh_option, 4, 1, NULL, | ||
686 | config_addr, | ||
687 | BUID_HI(pdn->phb->buid), | ||
688 | BUID_LO(pdn->phb->buid), | ||
689 | function); | ||
690 | |||
691 | if (rc) | 552 | if (rc) |
692 | printk(KERN_WARNING "EEH: Unexpected state change %d, err=%d dn=%s\n", | 553 | printk(KERN_WARNING "EEH: Unexpected state change %d, err=%d dn=%s\n", |
693 | function, rc, pdn->node->full_name); | 554 | function, rc, dn->full_name); |
694 | 555 | ||
695 | rc = eeh_wait_for_slot_status (pdn, PCI_BUS_RESET_WAIT_MSEC); | 556 | rc = eeh_ops->wait_state(dn, PCI_BUS_RESET_WAIT_MSEC); |
696 | if ((rc == 4) && (function == EEH_THAW_MMIO)) | 557 | if (rc > 0 && (rc & EEH_STATE_MMIO_ENABLED) && |
558 | (function == EEH_OPT_THAW_MMIO)) | ||
697 | return 0; | 559 | return 0; |
698 | 560 | ||
699 | return rc; | 561 | return rc; |
700 | } | 562 | } |
701 | 563 | ||
702 | /** | 564 | /** |
703 | * rtas_pci_slot_reset - raises/lowers the pci #RST line | ||
704 | * @pdn pci device node | ||
705 | * @state: 1/0 to raise/lower the #RST | ||
706 | * | ||
707 | * Clear the EEH-frozen condition on a slot. This routine | ||
708 | * asserts the PCI #RST line if the 'state' argument is '1', | ||
709 | * and drops the #RST line if 'state is '0'. This routine is | ||
710 | * safe to call in an interrupt context. | ||
711 | * | ||
712 | */ | ||
713 | |||
714 | static void | ||
715 | rtas_pci_slot_reset(struct pci_dn *pdn, int state) | ||
716 | { | ||
717 | int config_addr; | ||
718 | int rc; | ||
719 | |||
720 | BUG_ON (pdn==NULL); | ||
721 | |||
722 | if (!pdn->phb) { | ||
723 | printk (KERN_WARNING "EEH: in slot reset, device node %s has no phb\n", | ||
724 | pdn->node->full_name); | ||
725 | return; | ||
726 | } | ||
727 | |||
728 | /* Use PE configuration address, if present */ | ||
729 | config_addr = pdn->eeh_config_addr; | ||
730 | if (pdn->eeh_pe_config_addr) | ||
731 | config_addr = pdn->eeh_pe_config_addr; | ||
732 | |||
733 | rc = rtas_call(ibm_set_slot_reset, 4, 1, NULL, | ||
734 | config_addr, | ||
735 | BUID_HI(pdn->phb->buid), | ||
736 | BUID_LO(pdn->phb->buid), | ||
737 | state); | ||
738 | |||
739 | /* Fundamental-reset not supported on this PE, try hot-reset */ | ||
740 | if (rc == -8 && state == 3) { | ||
741 | rc = rtas_call(ibm_set_slot_reset, 4, 1, NULL, | ||
742 | config_addr, | ||
743 | BUID_HI(pdn->phb->buid), | ||
744 | BUID_LO(pdn->phb->buid), 1); | ||
745 | if (rc) | ||
746 | printk(KERN_WARNING | ||
747 | "EEH: Unable to reset the failed slot," | ||
748 | " #RST=%d dn=%s\n", | ||
749 | rc, pdn->node->full_name); | ||
750 | } | ||
751 | } | ||
752 | |||
753 | /** | ||
754 | * pcibios_set_pcie_slot_reset - Set PCI-E reset state | 565 | * pcibios_set_pcie_slot_reset - Set PCI-E reset state |
755 | * @dev: pci device struct | 566 | * @dev: pci device struct |
756 | * @state: reset state to enter | 567 | * @state: reset state to enter |
757 | * | 568 | * |
758 | * Return value: | 569 | * Return value: |
759 | * 0 if success | 570 | * 0 if success |
760 | **/ | 571 | */ |
761 | int pcibios_set_pcie_reset_state(struct pci_dev *dev, enum pcie_reset_state state) | 572 | int pcibios_set_pcie_reset_state(struct pci_dev *dev, enum pcie_reset_state state) |
762 | { | 573 | { |
763 | struct device_node *dn = pci_device_to_OF_node(dev); | 574 | struct device_node *dn = pci_device_to_OF_node(dev); |
764 | struct pci_dn *pdn = PCI_DN(dn); | ||
765 | 575 | ||
766 | switch (state) { | 576 | switch (state) { |
767 | case pcie_deassert_reset: | 577 | case pcie_deassert_reset: |
768 | rtas_pci_slot_reset(pdn, 0); | 578 | eeh_ops->reset(dn, EEH_RESET_DEACTIVATE); |
769 | break; | 579 | break; |
770 | case pcie_hot_reset: | 580 | case pcie_hot_reset: |
771 | rtas_pci_slot_reset(pdn, 1); | 581 | eeh_ops->reset(dn, EEH_RESET_HOT); |
772 | break; | 582 | break; |
773 | case pcie_warm_reset: | 583 | case pcie_warm_reset: |
774 | rtas_pci_slot_reset(pdn, 3); | 584 | eeh_ops->reset(dn, EEH_RESET_FUNDAMENTAL); |
775 | break; | 585 | break; |
776 | default: | 586 | default: |
777 | return -EINVAL; | 587 | return -EINVAL; |
@@ -781,13 +591,66 @@ int pcibios_set_pcie_reset_state(struct pci_dev *dev, enum pcie_reset_state stat | |||
781 | } | 591 | } |
782 | 592 | ||
783 | /** | 593 | /** |
784 | * rtas_set_slot_reset -- assert the pci #RST line for 1/4 second | 594 | * __eeh_set_pe_freset - Check the required reset for child devices |
785 | * @pdn: pci device node to be reset. | 595 | * @parent: parent device |
596 | * @freset: return value | ||
597 | * | ||
598 | * Each device might have its preferred reset type: fundamental or | ||
599 | * hot reset. The routine is used to collect the information from | ||
600 | * the child devices so that they could be reset accordingly. | ||
601 | */ | ||
602 | void __eeh_set_pe_freset(struct device_node *parent, unsigned int *freset) | ||
603 | { | ||
604 | struct device_node *dn; | ||
605 | |||
606 | for_each_child_of_node(parent, dn) { | ||
607 | if (of_node_to_eeh_dev(dn)) { | ||
608 | struct pci_dev *dev = of_node_to_eeh_dev(dn)->pdev; | ||
609 | |||
610 | if (dev && dev->driver) | ||
611 | *freset |= dev->needs_freset; | ||
612 | |||
613 | __eeh_set_pe_freset(dn, freset); | ||
614 | } | ||
615 | } | ||
616 | } | ||
617 | |||
618 | /** | ||
619 | * eeh_set_pe_freset - Check the required reset for the indicated device and its children | ||
620 | * @dn: parent device | ||
621 | * @freset: return value | ||
622 | * | ||
623 | * Each device might have its preferred reset type: fundamental or | ||
624 | * hot reset. The routine is used to collected the information for | ||
625 | * the indicated device and its children so that the bunch of the | ||
626 | * devices could be reset properly. | ||
786 | */ | 627 | */ |
628 | void eeh_set_pe_freset(struct device_node *dn, unsigned int *freset) | ||
629 | { | ||
630 | struct pci_dev *dev; | ||
631 | dn = eeh_find_device_pe(dn); | ||
632 | |||
633 | /* Back up one, since config addrs might be shared */ | ||
634 | if (!pcibios_find_pci_bus(dn) && of_node_to_eeh_dev(dn->parent)) | ||
635 | dn = dn->parent; | ||
636 | |||
637 | dev = of_node_to_eeh_dev(dn)->pdev; | ||
638 | if (dev) | ||
639 | *freset |= dev->needs_freset; | ||
787 | 640 | ||
788 | static void __rtas_set_slot_reset(struct pci_dn *pdn) | 641 | __eeh_set_pe_freset(dn, freset); |
642 | } | ||
643 | |||
644 | /** | ||
645 | * eeh_reset_pe_once - Assert the pci #RST line for 1/4 second | ||
646 | * @edev: pci device node to be reset. | ||
647 | * | ||
648 | * Assert the PCI #RST line for 1/4 second. | ||
649 | */ | ||
650 | static void eeh_reset_pe_once(struct eeh_dev *edev) | ||
789 | { | 651 | { |
790 | unsigned int freset = 0; | 652 | unsigned int freset = 0; |
653 | struct device_node *dn = eeh_dev_to_of_node(edev); | ||
791 | 654 | ||
792 | /* Determine type of EEH reset required for | 655 | /* Determine type of EEH reset required for |
793 | * Partitionable Endpoint, a hot-reset (1) | 656 | * Partitionable Endpoint, a hot-reset (1) |
@@ -795,58 +658,68 @@ static void __rtas_set_slot_reset(struct pci_dn *pdn) | |||
795 | * A fundamental reset required by any device under | 658 | * A fundamental reset required by any device under |
796 | * Partitionable Endpoint trumps hot-reset. | 659 | * Partitionable Endpoint trumps hot-reset. |
797 | */ | 660 | */ |
798 | eeh_set_pe_freset(pdn->node, &freset); | 661 | eeh_set_pe_freset(dn, &freset); |
799 | 662 | ||
800 | if (freset) | 663 | if (freset) |
801 | rtas_pci_slot_reset(pdn, 3); | 664 | eeh_ops->reset(dn, EEH_RESET_FUNDAMENTAL); |
802 | else | 665 | else |
803 | rtas_pci_slot_reset(pdn, 1); | 666 | eeh_ops->reset(dn, EEH_RESET_HOT); |
804 | 667 | ||
805 | /* The PCI bus requires that the reset be held high for at least | 668 | /* 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'. */ | 669 | * a 100 milliseconds. We wait a bit longer 'just in case'. |
807 | 670 | */ | |
808 | #define PCI_BUS_RST_HOLD_TIME_MSEC 250 | 671 | #define PCI_BUS_RST_HOLD_TIME_MSEC 250 |
809 | msleep (PCI_BUS_RST_HOLD_TIME_MSEC); | 672 | msleep(PCI_BUS_RST_HOLD_TIME_MSEC); |
810 | 673 | ||
811 | /* We might get hit with another EEH freeze as soon as the | 674 | /* 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 | 675 | * pci slot reset line is dropped. Make sure we don't miss |
813 | * these, and clear the flag now. */ | 676 | * these, and clear the flag now. |
814 | eeh_clear_slot (pdn->node, EEH_MODE_ISOLATED); | 677 | */ |
678 | eeh_clear_slot(dn, EEH_MODE_ISOLATED); | ||
815 | 679 | ||
816 | rtas_pci_slot_reset (pdn, 0); | 680 | eeh_ops->reset(dn, EEH_RESET_DEACTIVATE); |
817 | 681 | ||
818 | /* After a PCI slot has been reset, the PCI Express spec requires | 682 | /* 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 | 683 | * a 1.5 second idle time for the bus to stabilize, before starting |
820 | * up traffic. */ | 684 | * up traffic. |
685 | */ | ||
821 | #define PCI_BUS_SETTLE_TIME_MSEC 1800 | 686 | #define PCI_BUS_SETTLE_TIME_MSEC 1800 |
822 | msleep (PCI_BUS_SETTLE_TIME_MSEC); | 687 | msleep(PCI_BUS_SETTLE_TIME_MSEC); |
823 | } | 688 | } |
824 | 689 | ||
825 | int rtas_set_slot_reset(struct pci_dn *pdn) | 690 | /** |
691 | * eeh_reset_pe - Reset the indicated PE | ||
692 | * @edev: PCI device associated EEH device | ||
693 | * | ||
694 | * This routine should be called to reset indicated device, including | ||
695 | * PE. A PE might include multiple PCI devices and sometimes PCI bridges | ||
696 | * might be involved as well. | ||
697 | */ | ||
698 | int eeh_reset_pe(struct eeh_dev *edev) | ||
826 | { | 699 | { |
827 | int i, rc; | 700 | int i, rc; |
701 | struct device_node *dn = eeh_dev_to_of_node(edev); | ||
828 | 702 | ||
829 | /* Take three shots at resetting the bus */ | 703 | /* Take three shots at resetting the bus */ |
830 | for (i=0; i<3; i++) { | 704 | for (i=0; i<3; i++) { |
831 | __rtas_set_slot_reset(pdn); | 705 | eeh_reset_pe_once(edev); |
832 | 706 | ||
833 | rc = eeh_wait_for_slot_status(pdn, PCI_BUS_RESET_WAIT_MSEC); | 707 | rc = eeh_ops->wait_state(dn, PCI_BUS_RESET_WAIT_MSEC); |
834 | if (rc == 0) | 708 | if (rc == (EEH_STATE_MMIO_ACTIVE | EEH_STATE_DMA_ACTIVE)) |
835 | return 0; | 709 | return 0; |
836 | 710 | ||
837 | if (rc < 0) { | 711 | if (rc < 0) { |
838 | printk(KERN_ERR "EEH: unrecoverable slot failure %s\n", | 712 | printk(KERN_ERR "EEH: unrecoverable slot failure %s\n", |
839 | pdn->node->full_name); | 713 | dn->full_name); |
840 | return -1; | 714 | return -1; |
841 | } | 715 | } |
842 | printk(KERN_ERR "EEH: bus reset %d failed on slot %s, rc=%d\n", | 716 | printk(KERN_ERR "EEH: bus reset %d failed on slot %s, rc=%d\n", |
843 | i+1, pdn->node->full_name, rc); | 717 | i+1, dn->full_name, rc); |
844 | } | 718 | } |
845 | 719 | ||
846 | return -1; | 720 | return -1; |
847 | } | 721 | } |
848 | 722 | ||
849 | /* ------------------------------------------------------- */ | ||
850 | /** Save and restore of PCI BARs | 723 | /** Save and restore of PCI BARs |
851 | * | 724 | * |
852 | * Although firmware will set up BARs during boot, it doesn't | 725 | * Although firmware will set up BARs during boot, it doesn't |
@@ -856,181 +729,122 @@ int rtas_set_slot_reset(struct pci_dn *pdn) | |||
856 | */ | 729 | */ |
857 | 730 | ||
858 | /** | 731 | /** |
859 | * __restore_bars - Restore the Base Address Registers | 732 | * eeh_restore_one_device_bars - Restore the Base Address Registers for one device |
860 | * @pdn: pci device node | 733 | * @edev: PCI device associated EEH device |
861 | * | 734 | * |
862 | * Loads the PCI configuration space base address registers, | 735 | * Loads the PCI configuration space base address registers, |
863 | * the expansion ROM base address, the latency timer, and etc. | 736 | * the expansion ROM base address, the latency timer, and etc. |
864 | * from the saved values in the device node. | 737 | * from the saved values in the device node. |
865 | */ | 738 | */ |
866 | static inline void __restore_bars (struct pci_dn *pdn) | 739 | static inline void eeh_restore_one_device_bars(struct eeh_dev *edev) |
867 | { | 740 | { |
868 | int i; | 741 | int i; |
869 | u32 cmd; | 742 | u32 cmd; |
743 | struct device_node *dn = eeh_dev_to_of_node(edev); | ||
744 | |||
745 | if (!edev->phb) | ||
746 | return; | ||
870 | 747 | ||
871 | if (NULL==pdn->phb) return; | ||
872 | for (i=4; i<10; i++) { | 748 | for (i=4; i<10; i++) { |
873 | rtas_write_config(pdn, i*4, 4, pdn->config_space[i]); | 749 | eeh_ops->write_config(dn, i*4, 4, edev->config_space[i]); |
874 | } | 750 | } |
875 | 751 | ||
876 | /* 12 == Expansion ROM Address */ | 752 | /* 12 == Expansion ROM Address */ |
877 | rtas_write_config(pdn, 12*4, 4, pdn->config_space[12]); | 753 | eeh_ops->write_config(dn, 12*4, 4, edev->config_space[12]); |
878 | 754 | ||
879 | #define BYTE_SWAP(OFF) (8*((OFF)/4)+3-(OFF)) | 755 | #define BYTE_SWAP(OFF) (8*((OFF)/4)+3-(OFF)) |
880 | #define SAVED_BYTE(OFF) (((u8 *)(pdn->config_space))[BYTE_SWAP(OFF)]) | 756 | #define SAVED_BYTE(OFF) (((u8 *)(edev->config_space))[BYTE_SWAP(OFF)]) |
881 | 757 | ||
882 | rtas_write_config (pdn, PCI_CACHE_LINE_SIZE, 1, | 758 | eeh_ops->write_config(dn, PCI_CACHE_LINE_SIZE, 1, |
883 | SAVED_BYTE(PCI_CACHE_LINE_SIZE)); | 759 | SAVED_BYTE(PCI_CACHE_LINE_SIZE)); |
884 | 760 | ||
885 | rtas_write_config (pdn, PCI_LATENCY_TIMER, 1, | 761 | eeh_ops->write_config(dn, PCI_LATENCY_TIMER, 1, |
886 | SAVED_BYTE(PCI_LATENCY_TIMER)); | 762 | SAVED_BYTE(PCI_LATENCY_TIMER)); |
887 | 763 | ||
888 | /* max latency, min grant, interrupt pin and line */ | 764 | /* max latency, min grant, interrupt pin and line */ |
889 | rtas_write_config(pdn, 15*4, 4, pdn->config_space[15]); | 765 | eeh_ops->write_config(dn, 15*4, 4, edev->config_space[15]); |
890 | 766 | ||
891 | /* Restore PERR & SERR bits, some devices require it, | 767 | /* Restore PERR & SERR bits, some devices require it, |
892 | don't touch the other command bits */ | 768 | * don't touch the other command bits |
893 | rtas_read_config(pdn, PCI_COMMAND, 4, &cmd); | 769 | */ |
894 | if (pdn->config_space[1] & PCI_COMMAND_PARITY) | 770 | eeh_ops->read_config(dn, PCI_COMMAND, 4, &cmd); |
771 | if (edev->config_space[1] & PCI_COMMAND_PARITY) | ||
895 | cmd |= PCI_COMMAND_PARITY; | 772 | cmd |= PCI_COMMAND_PARITY; |
896 | else | 773 | else |
897 | cmd &= ~PCI_COMMAND_PARITY; | 774 | cmd &= ~PCI_COMMAND_PARITY; |
898 | if (pdn->config_space[1] & PCI_COMMAND_SERR) | 775 | if (edev->config_space[1] & PCI_COMMAND_SERR) |
899 | cmd |= PCI_COMMAND_SERR; | 776 | cmd |= PCI_COMMAND_SERR; |
900 | else | 777 | else |
901 | cmd &= ~PCI_COMMAND_SERR; | 778 | cmd &= ~PCI_COMMAND_SERR; |
902 | rtas_write_config(pdn, PCI_COMMAND, 4, cmd); | 779 | eeh_ops->write_config(dn, PCI_COMMAND, 4, cmd); |
903 | } | 780 | } |
904 | 781 | ||
905 | /** | 782 | /** |
906 | * eeh_restore_bars - restore the PCI config space info | 783 | * eeh_restore_bars - Restore the PCI config space info |
784 | * @edev: EEH device | ||
907 | * | 785 | * |
908 | * This routine performs a recursive walk to the children | 786 | * This routine performs a recursive walk to the children |
909 | * of this device as well. | 787 | * of this device as well. |
910 | */ | 788 | */ |
911 | void eeh_restore_bars(struct pci_dn *pdn) | 789 | void eeh_restore_bars(struct eeh_dev *edev) |
912 | { | 790 | { |
913 | struct device_node *dn; | 791 | struct device_node *dn; |
914 | if (!pdn) | 792 | if (!edev) |
915 | return; | 793 | return; |
916 | 794 | ||
917 | if ((pdn->eeh_mode & EEH_MODE_SUPPORTED) && !IS_BRIDGE(pdn->class_code)) | 795 | if ((edev->mode & EEH_MODE_SUPPORTED) && !IS_BRIDGE(edev->class_code)) |
918 | __restore_bars (pdn); | 796 | eeh_restore_one_device_bars(edev); |
919 | 797 | ||
920 | for_each_child_of_node(pdn->node, dn) | 798 | for_each_child_of_node(eeh_dev_to_of_node(edev), dn) |
921 | eeh_restore_bars (PCI_DN(dn)); | 799 | eeh_restore_bars(of_node_to_eeh_dev(dn)); |
922 | } | 800 | } |
923 | 801 | ||
924 | /** | 802 | /** |
925 | * eeh_save_bars - save device bars | 803 | * eeh_save_bars - Save device bars |
804 | * @edev: PCI device associated EEH device | ||
926 | * | 805 | * |
927 | * Save the values of the device bars. Unlike the restore | 806 | * Save the values of the device bars. Unlike the restore |
928 | * routine, this routine is *not* recursive. This is because | 807 | * routine, this routine is *not* recursive. This is because |
929 | * PCI devices are added individually; but, for the restore, | 808 | * PCI devices are added individually; but, for the restore, |
930 | * an entire slot is reset at a time. | 809 | * an entire slot is reset at a time. |
931 | */ | 810 | */ |
932 | static void eeh_save_bars(struct pci_dn *pdn) | 811 | static void eeh_save_bars(struct eeh_dev *edev) |
933 | { | 812 | { |
934 | int i; | 813 | int i; |
814 | struct device_node *dn; | ||
935 | 815 | ||
936 | if (!pdn ) | 816 | if (!edev) |
937 | return; | 817 | return; |
818 | dn = eeh_dev_to_of_node(edev); | ||
938 | 819 | ||
939 | for (i = 0; i < 16; i++) | 820 | for (i = 0; i < 16; i++) |
940 | rtas_read_config(pdn, i * 4, 4, &pdn->config_space[i]); | 821 | eeh_ops->read_config(dn, i * 4, 4, &edev->config_space[i]); |
941 | } | ||
942 | |||
943 | void | ||
944 | rtas_configure_bridge(struct pci_dn *pdn) | ||
945 | { | ||
946 | int config_addr; | ||
947 | int rc; | ||
948 | int token; | ||
949 | |||
950 | /* Use PE configuration address, if present */ | ||
951 | config_addr = pdn->eeh_config_addr; | ||
952 | if (pdn->eeh_pe_config_addr) | ||
953 | config_addr = pdn->eeh_pe_config_addr; | ||
954 | |||
955 | /* Use new configure-pe function, if supported */ | ||
956 | if (ibm_configure_pe != RTAS_UNKNOWN_SERVICE) | ||
957 | token = ibm_configure_pe; | ||
958 | else | ||
959 | token = ibm_configure_bridge; | ||
960 | |||
961 | rc = rtas_call(token, 3, 1, NULL, | ||
962 | config_addr, | ||
963 | BUID_HI(pdn->phb->buid), | ||
964 | BUID_LO(pdn->phb->buid)); | ||
965 | if (rc) { | ||
966 | printk (KERN_WARNING "EEH: Unable to configure device bridge (%d) for %s\n", | ||
967 | rc, pdn->node->full_name); | ||
968 | } | ||
969 | } | 822 | } |
970 | 823 | ||
971 | /* ------------------------------------------------------------- */ | 824 | /** |
972 | /* The code below deals with enabling EEH for devices during the | 825 | * eeh_early_enable - Early enable EEH on the indicated device |
973 | * early boot sequence. EEH must be enabled before any PCI probing | 826 | * @dn: device node |
974 | * can be done. | 827 | * @data: BUID |
828 | * | ||
829 | * Enable EEH functionality on the specified PCI device. The function | ||
830 | * is expected to be called before real PCI probing is done. However, | ||
831 | * the PHBs have been initialized at this point. | ||
975 | */ | 832 | */ |
976 | 833 | static void *eeh_early_enable(struct device_node *dn, void *data) | |
977 | #define EEH_ENABLE 1 | ||
978 | |||
979 | struct eeh_early_enable_info { | ||
980 | unsigned int buid_hi; | ||
981 | unsigned int buid_lo; | ||
982 | }; | ||
983 | |||
984 | static int get_pe_addr (int config_addr, | ||
985 | struct eeh_early_enable_info *info) | ||
986 | { | 834 | { |
987 | unsigned int rets[3]; | ||
988 | int ret; | ||
989 | |||
990 | /* Use latest config-addr token on power6 */ | ||
991 | if (ibm_get_config_addr_info2 != RTAS_UNKNOWN_SERVICE) { | ||
992 | /* Make sure we have a PE in hand */ | ||
993 | ret = rtas_call (ibm_get_config_addr_info2, 4, 2, rets, | ||
994 | config_addr, info->buid_hi, info->buid_lo, 1); | ||
995 | if (ret || (rets[0]==0)) | ||
996 | return 0; | ||
997 | |||
998 | ret = rtas_call (ibm_get_config_addr_info2, 4, 2, rets, | ||
999 | config_addr, info->buid_hi, info->buid_lo, 0); | ||
1000 | if (ret) | ||
1001 | return 0; | ||
1002 | return rets[0]; | ||
1003 | } | ||
1004 | |||
1005 | /* Use older config-addr token on power5 */ | ||
1006 | if (ibm_get_config_addr_info != RTAS_UNKNOWN_SERVICE) { | ||
1007 | ret = rtas_call (ibm_get_config_addr_info, 4, 2, rets, | ||
1008 | config_addr, info->buid_hi, info->buid_lo, 0); | ||
1009 | if (ret) | ||
1010 | return 0; | ||
1011 | return rets[0]; | ||
1012 | } | ||
1013 | return 0; | ||
1014 | } | ||
1015 | |||
1016 | /* Enable eeh for the given device node. */ | ||
1017 | static void *early_enable_eeh(struct device_node *dn, void *data) | ||
1018 | { | ||
1019 | unsigned int rets[3]; | ||
1020 | struct eeh_early_enable_info *info = data; | ||
1021 | int ret; | 835 | int ret; |
1022 | const u32 *class_code = of_get_property(dn, "class-code", NULL); | 836 | const u32 *class_code = of_get_property(dn, "class-code", NULL); |
1023 | const u32 *vendor_id = of_get_property(dn, "vendor-id", NULL); | 837 | const u32 *vendor_id = of_get_property(dn, "vendor-id", NULL); |
1024 | const u32 *device_id = of_get_property(dn, "device-id", NULL); | 838 | const u32 *device_id = of_get_property(dn, "device-id", NULL); |
1025 | const u32 *regs; | 839 | const u32 *regs; |
1026 | int enable; | 840 | int enable; |
1027 | struct pci_dn *pdn = PCI_DN(dn); | 841 | struct eeh_dev *edev = of_node_to_eeh_dev(dn); |
1028 | 842 | ||
1029 | pdn->class_code = 0; | 843 | edev->class_code = 0; |
1030 | pdn->eeh_mode = 0; | 844 | edev->mode = 0; |
1031 | pdn->eeh_check_count = 0; | 845 | edev->check_count = 0; |
1032 | pdn->eeh_freeze_count = 0; | 846 | edev->freeze_count = 0; |
1033 | pdn->eeh_false_positives = 0; | 847 | edev->false_positives = 0; |
1034 | 848 | ||
1035 | if (!of_device_is_available(dn)) | 849 | if (!of_device_is_available(dn)) |
1036 | return NULL; | 850 | return NULL; |
@@ -1041,54 +855,56 @@ static void *early_enable_eeh(struct device_node *dn, void *data) | |||
1041 | 855 | ||
1042 | /* There is nothing to check on PCI to ISA bridges */ | 856 | /* There is nothing to check on PCI to ISA bridges */ |
1043 | if (dn->type && !strcmp(dn->type, "isa")) { | 857 | if (dn->type && !strcmp(dn->type, "isa")) { |
1044 | pdn->eeh_mode |= EEH_MODE_NOCHECK; | 858 | edev->mode |= EEH_MODE_NOCHECK; |
1045 | return NULL; | 859 | return NULL; |
1046 | } | 860 | } |
1047 | pdn->class_code = *class_code; | 861 | edev->class_code = *class_code; |
1048 | 862 | ||
1049 | /* Ok... see if this device supports EEH. Some do, some don't, | 863 | /* 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. */ | 864 | * and the only way to find out is to check each and every one. |
865 | */ | ||
1051 | regs = of_get_property(dn, "reg", NULL); | 866 | regs = of_get_property(dn, "reg", NULL); |
1052 | if (regs) { | 867 | if (regs) { |
1053 | /* First register entry is addr (00BBSS00) */ | 868 | /* First register entry is addr (00BBSS00) */ |
1054 | /* Try to enable eeh */ | 869 | /* Try to enable eeh */ |
1055 | ret = rtas_call(ibm_set_eeh_option, 4, 1, NULL, | 870 | ret = eeh_ops->set_option(dn, EEH_OPT_ENABLE); |
1056 | regs[0], info->buid_hi, info->buid_lo, | ||
1057 | EEH_ENABLE); | ||
1058 | 871 | ||
1059 | enable = 0; | 872 | enable = 0; |
1060 | if (ret == 0) { | 873 | if (ret == 0) { |
1061 | pdn->eeh_config_addr = regs[0]; | 874 | edev->config_addr = regs[0]; |
1062 | 875 | ||
1063 | /* If the newer, better, ibm,get-config-addr-info is supported, | 876 | /* If the newer, better, ibm,get-config-addr-info is supported, |
1064 | * then use that instead. */ | 877 | * then use that instead. |
1065 | pdn->eeh_pe_config_addr = get_pe_addr(pdn->eeh_config_addr, info); | 878 | */ |
879 | edev->pe_config_addr = eeh_ops->get_pe_addr(dn); | ||
1066 | 880 | ||
1067 | /* Some older systems (Power4) allow the | 881 | /* Some older systems (Power4) allow the |
1068 | * ibm,set-eeh-option call to succeed even on nodes | 882 | * ibm,set-eeh-option call to succeed even on nodes |
1069 | * where EEH is not supported. Verify support | 883 | * where EEH is not supported. Verify support |
1070 | * explicitly. */ | 884 | * explicitly. |
1071 | ret = read_slot_reset_state(pdn, rets); | 885 | */ |
1072 | if ((ret == 0) && (rets[1] == 1)) | 886 | ret = eeh_ops->get_state(dn, NULL); |
887 | if (ret > 0 && ret != EEH_STATE_NOT_SUPPORT) | ||
1073 | enable = 1; | 888 | enable = 1; |
1074 | } | 889 | } |
1075 | 890 | ||
1076 | if (enable) { | 891 | if (enable) { |
1077 | eeh_subsystem_enabled = 1; | 892 | eeh_subsystem_enabled = 1; |
1078 | pdn->eeh_mode |= EEH_MODE_SUPPORTED; | 893 | edev->mode |= EEH_MODE_SUPPORTED; |
1079 | 894 | ||
1080 | pr_debug("EEH: %s: eeh enabled, config=%x pe_config=%x\n", | 895 | pr_debug("EEH: %s: eeh enabled, config=%x pe_config=%x\n", |
1081 | dn->full_name, pdn->eeh_config_addr, | 896 | dn->full_name, edev->config_addr, |
1082 | pdn->eeh_pe_config_addr); | 897 | edev->pe_config_addr); |
1083 | } else { | 898 | } else { |
1084 | 899 | ||
1085 | /* This device doesn't support EEH, but it may have an | 900 | /* This device doesn't support EEH, but it may have an |
1086 | * EEH parent, in which case we mark it as supported. */ | 901 | * EEH parent, in which case we mark it as supported. |
1087 | if (dn->parent && PCI_DN(dn->parent) | 902 | */ |
1088 | && (PCI_DN(dn->parent)->eeh_mode & EEH_MODE_SUPPORTED)) { | 903 | if (dn->parent && of_node_to_eeh_dev(dn->parent) && |
904 | (of_node_to_eeh_dev(dn->parent)->mode & EEH_MODE_SUPPORTED)) { | ||
1089 | /* Parent supports EEH. */ | 905 | /* Parent supports EEH. */ |
1090 | pdn->eeh_mode |= EEH_MODE_SUPPORTED; | 906 | edev->mode |= EEH_MODE_SUPPORTED; |
1091 | pdn->eeh_config_addr = PCI_DN(dn->parent)->eeh_config_addr; | 907 | edev->config_addr = of_node_to_eeh_dev(dn->parent)->config_addr; |
1092 | return NULL; | 908 | return NULL; |
1093 | } | 909 | } |
1094 | } | 910 | } |
@@ -1097,11 +913,63 @@ static void *early_enable_eeh(struct device_node *dn, void *data) | |||
1097 | dn->full_name); | 913 | dn->full_name); |
1098 | } | 914 | } |
1099 | 915 | ||
1100 | eeh_save_bars(pdn); | 916 | eeh_save_bars(edev); |
1101 | return NULL; | 917 | return NULL; |
1102 | } | 918 | } |
1103 | 919 | ||
1104 | /* | 920 | /** |
921 | * eeh_ops_register - Register platform dependent EEH operations | ||
922 | * @ops: platform dependent EEH operations | ||
923 | * | ||
924 | * Register the platform dependent EEH operation callback | ||
925 | * functions. The platform should call this function before | ||
926 | * any other EEH operations. | ||
927 | */ | ||
928 | int __init eeh_ops_register(struct eeh_ops *ops) | ||
929 | { | ||
930 | if (!ops->name) { | ||
931 | pr_warning("%s: Invalid EEH ops name for %p\n", | ||
932 | __func__, ops); | ||
933 | return -EINVAL; | ||
934 | } | ||
935 | |||
936 | if (eeh_ops && eeh_ops != ops) { | ||
937 | pr_warning("%s: EEH ops of platform %s already existing (%s)\n", | ||
938 | __func__, eeh_ops->name, ops->name); | ||
939 | return -EEXIST; | ||
940 | } | ||
941 | |||
942 | eeh_ops = ops; | ||
943 | |||
944 | return 0; | ||
945 | } | ||
946 | |||
947 | /** | ||
948 | * eeh_ops_unregister - Unreigster platform dependent EEH operations | ||
949 | * @name: name of EEH platform operations | ||
950 | * | ||
951 | * Unregister the platform dependent EEH operation callback | ||
952 | * functions. | ||
953 | */ | ||
954 | int __exit eeh_ops_unregister(const char *name) | ||
955 | { | ||
956 | if (!name || !strlen(name)) { | ||
957 | pr_warning("%s: Invalid EEH ops name\n", | ||
958 | __func__); | ||
959 | return -EINVAL; | ||
960 | } | ||
961 | |||
962 | if (eeh_ops && !strcmp(eeh_ops->name, name)) { | ||
963 | eeh_ops = NULL; | ||
964 | return 0; | ||
965 | } | ||
966 | |||
967 | return -EEXIST; | ||
968 | } | ||
969 | |||
970 | /** | ||
971 | * eeh_init - EEH initialization | ||
972 | * | ||
1105 | * Initialize EEH by trying to enable it for all of the adapters in the system. | 973 | * 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. | 974 | * 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 | 975 | * Note that we leave EEH on so failed config cycles won't cause a machine |
@@ -1117,50 +985,35 @@ static void *early_enable_eeh(struct device_node *dn, void *data) | |||
1117 | void __init eeh_init(void) | 985 | void __init eeh_init(void) |
1118 | { | 986 | { |
1119 | struct device_node *phb, *np; | 987 | struct device_node *phb, *np; |
1120 | struct eeh_early_enable_info info; | 988 | int ret; |
989 | |||
990 | /* call platform initialization function */ | ||
991 | if (!eeh_ops) { | ||
992 | pr_warning("%s: Platform EEH operation not found\n", | ||
993 | __func__); | ||
994 | return; | ||
995 | } else if ((ret = eeh_ops->init())) { | ||
996 | pr_warning("%s: Failed to call platform init function (%d)\n", | ||
997 | __func__, ret); | ||
998 | return; | ||
999 | } | ||
1121 | 1000 | ||
1122 | raw_spin_lock_init(&confirm_error_lock); | 1001 | raw_spin_lock_init(&confirm_error_lock); |
1123 | spin_lock_init(&slot_errbuf_lock); | ||
1124 | 1002 | ||
1125 | np = of_find_node_by_path("/rtas"); | 1003 | np = of_find_node_by_path("/rtas"); |
1126 | if (np == NULL) | 1004 | if (np == NULL) |
1127 | return; | 1005 | return; |
1128 | 1006 | ||
1129 | ibm_set_eeh_option = rtas_token("ibm,set-eeh-option"); | ||
1130 | ibm_set_slot_reset = rtas_token("ibm,set-slot-reset"); | ||
1131 | ibm_read_slot_reset_state2 = rtas_token("ibm,read-slot-reset-state2"); | ||
1132 | ibm_read_slot_reset_state = rtas_token("ibm,read-slot-reset-state"); | ||
1133 | ibm_slot_error_detail = rtas_token("ibm,slot-error-detail"); | ||
1134 | 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"); | ||
1136 | ibm_configure_bridge = rtas_token ("ibm,configure-bridge"); | ||
1137 | ibm_configure_pe = rtas_token("ibm,configure-pe"); | ||
1138 | |||
1139 | if (ibm_set_eeh_option == RTAS_UNKNOWN_SERVICE) | ||
1140 | return; | ||
1141 | |||
1142 | eeh_error_buf_size = rtas_token("rtas-error-log-max"); | ||
1143 | if (eeh_error_buf_size == RTAS_UNKNOWN_SERVICE) { | ||
1144 | eeh_error_buf_size = 1024; | ||
1145 | } | ||
1146 | if (eeh_error_buf_size > RTAS_ERROR_LOG_MAX) { | ||
1147 | printk(KERN_WARNING "EEH: rtas-error-log-max is bigger than allocated " | ||
1148 | "buffer ! (%d vs %d)", eeh_error_buf_size, RTAS_ERROR_LOG_MAX); | ||
1149 | eeh_error_buf_size = RTAS_ERROR_LOG_MAX; | ||
1150 | } | ||
1151 | |||
1152 | /* Enable EEH for all adapters. Note that eeh requires buid's */ | 1007 | /* Enable EEH for all adapters. Note that eeh requires buid's */ |
1153 | for (phb = of_find_node_by_name(NULL, "pci"); phb; | 1008 | for (phb = of_find_node_by_name(NULL, "pci"); phb; |
1154 | phb = of_find_node_by_name(phb, "pci")) { | 1009 | phb = of_find_node_by_name(phb, "pci")) { |
1155 | unsigned long buid; | 1010 | unsigned long buid; |
1156 | 1011 | ||
1157 | buid = get_phb_buid(phb); | 1012 | buid = get_phb_buid(phb); |
1158 | if (buid == 0 || PCI_DN(phb) == NULL) | 1013 | if (buid == 0 || !of_node_to_eeh_dev(phb)) |
1159 | continue; | 1014 | continue; |
1160 | 1015 | ||
1161 | info.buid_lo = BUID_LO(buid); | 1016 | traverse_pci_devices(phb, eeh_early_enable, NULL); |
1162 | info.buid_hi = BUID_HI(buid); | ||
1163 | traverse_pci_devices(phb, early_enable_eeh, &info); | ||
1164 | } | 1017 | } |
1165 | 1018 | ||
1166 | if (eeh_subsystem_enabled) | 1019 | if (eeh_subsystem_enabled) |
@@ -1170,7 +1023,7 @@ void __init eeh_init(void) | |||
1170 | } | 1023 | } |
1171 | 1024 | ||
1172 | /** | 1025 | /** |
1173 | * eeh_add_device_early - enable EEH for the indicated device_node | 1026 | * eeh_add_device_early - Enable EEH for the indicated device_node |
1174 | * @dn: device node for which to set up EEH | 1027 | * @dn: device node for which to set up EEH |
1175 | * | 1028 | * |
1176 | * This routine must be used to perform EEH initialization for PCI | 1029 | * This routine must be used to perform EEH initialization for PCI |
@@ -1184,21 +1037,26 @@ void __init eeh_init(void) | |||
1184 | static void eeh_add_device_early(struct device_node *dn) | 1037 | static void eeh_add_device_early(struct device_node *dn) |
1185 | { | 1038 | { |
1186 | struct pci_controller *phb; | 1039 | struct pci_controller *phb; |
1187 | struct eeh_early_enable_info info; | ||
1188 | 1040 | ||
1189 | if (!dn || !PCI_DN(dn)) | 1041 | if (!dn || !of_node_to_eeh_dev(dn)) |
1190 | return; | 1042 | return; |
1191 | phb = PCI_DN(dn)->phb; | 1043 | phb = of_node_to_eeh_dev(dn)->phb; |
1192 | 1044 | ||
1193 | /* USB Bus children of PCI devices will not have BUID's */ | 1045 | /* USB Bus children of PCI devices will not have BUID's */ |
1194 | if (NULL == phb || 0 == phb->buid) | 1046 | if (NULL == phb || 0 == phb->buid) |
1195 | return; | 1047 | return; |
1196 | 1048 | ||
1197 | info.buid_hi = BUID_HI(phb->buid); | 1049 | eeh_early_enable(dn, NULL); |
1198 | info.buid_lo = BUID_LO(phb->buid); | ||
1199 | early_enable_eeh(dn, &info); | ||
1200 | } | 1050 | } |
1201 | 1051 | ||
1052 | /** | ||
1053 | * eeh_add_device_tree_early - Enable EEH for the indicated device | ||
1054 | * @dn: device node | ||
1055 | * | ||
1056 | * This routine must be used to perform EEH initialization for the | ||
1057 | * indicated PCI device that was added after system boot (e.g. | ||
1058 | * hotplug, dlpar). | ||
1059 | */ | ||
1202 | void eeh_add_device_tree_early(struct device_node *dn) | 1060 | void eeh_add_device_tree_early(struct device_node *dn) |
1203 | { | 1061 | { |
1204 | struct device_node *sib; | 1062 | struct device_node *sib; |
@@ -1210,7 +1068,7 @@ void eeh_add_device_tree_early(struct device_node *dn) | |||
1210 | EXPORT_SYMBOL_GPL(eeh_add_device_tree_early); | 1068 | EXPORT_SYMBOL_GPL(eeh_add_device_tree_early); |
1211 | 1069 | ||
1212 | /** | 1070 | /** |
1213 | * eeh_add_device_late - perform EEH initialization for the indicated pci device | 1071 | * eeh_add_device_late - Perform EEH initialization for the indicated pci device |
1214 | * @dev: pci device for which to set up EEH | 1072 | * @dev: pci device for which to set up EEH |
1215 | * | 1073 | * |
1216 | * This routine must be used to complete EEH initialization for PCI | 1074 | * This routine must be used to complete EEH initialization for PCI |
@@ -1219,7 +1077,7 @@ EXPORT_SYMBOL_GPL(eeh_add_device_tree_early); | |||
1219 | static void eeh_add_device_late(struct pci_dev *dev) | 1077 | static void eeh_add_device_late(struct pci_dev *dev) |
1220 | { | 1078 | { |
1221 | struct device_node *dn; | 1079 | struct device_node *dn; |
1222 | struct pci_dn *pdn; | 1080 | struct eeh_dev *edev; |
1223 | 1081 | ||
1224 | if (!dev || !eeh_subsystem_enabled) | 1082 | if (!dev || !eeh_subsystem_enabled) |
1225 | return; | 1083 | return; |
@@ -1227,20 +1085,29 @@ static void eeh_add_device_late(struct pci_dev *dev) | |||
1227 | pr_debug("EEH: Adding device %s\n", pci_name(dev)); | 1085 | pr_debug("EEH: Adding device %s\n", pci_name(dev)); |
1228 | 1086 | ||
1229 | dn = pci_device_to_OF_node(dev); | 1087 | dn = pci_device_to_OF_node(dev); |
1230 | pdn = PCI_DN(dn); | 1088 | edev = pci_dev_to_eeh_dev(dev); |
1231 | if (pdn->pcidev == dev) { | 1089 | if (edev->pdev == dev) { |
1232 | pr_debug("EEH: Already referenced !\n"); | 1090 | pr_debug("EEH: Already referenced !\n"); |
1233 | return; | 1091 | return; |
1234 | } | 1092 | } |
1235 | WARN_ON(pdn->pcidev); | 1093 | WARN_ON(edev->pdev); |
1236 | 1094 | ||
1237 | pci_dev_get (dev); | 1095 | pci_dev_get(dev); |
1238 | pdn->pcidev = dev; | 1096 | edev->pdev = dev; |
1097 | dev->dev.archdata.edev = edev; | ||
1239 | 1098 | ||
1240 | pci_addr_cache_insert_device(dev); | 1099 | pci_addr_cache_insert_device(dev); |
1241 | eeh_sysfs_add_device(dev); | 1100 | eeh_sysfs_add_device(dev); |
1242 | } | 1101 | } |
1243 | 1102 | ||
1103 | /** | ||
1104 | * eeh_add_device_tree_late - Perform EEH initialization for the indicated PCI bus | ||
1105 | * @bus: PCI bus | ||
1106 | * | ||
1107 | * This routine must be used to perform EEH initialization for PCI | ||
1108 | * devices which are attached to the indicated PCI bus. The PCI bus | ||
1109 | * is added after system boot through hotplug or dlpar. | ||
1110 | */ | ||
1244 | void eeh_add_device_tree_late(struct pci_bus *bus) | 1111 | void eeh_add_device_tree_late(struct pci_bus *bus) |
1245 | { | 1112 | { |
1246 | struct pci_dev *dev; | 1113 | struct pci_dev *dev; |
@@ -1257,7 +1124,7 @@ void eeh_add_device_tree_late(struct pci_bus *bus) | |||
1257 | EXPORT_SYMBOL_GPL(eeh_add_device_tree_late); | 1124 | EXPORT_SYMBOL_GPL(eeh_add_device_tree_late); |
1258 | 1125 | ||
1259 | /** | 1126 | /** |
1260 | * eeh_remove_device - undo EEH setup for the indicated pci device | 1127 | * eeh_remove_device - Undo EEH setup for the indicated pci device |
1261 | * @dev: pci device to be removed | 1128 | * @dev: pci device to be removed |
1262 | * | 1129 | * |
1263 | * This routine should be called when a device is removed from | 1130 | * This routine should be called when a device is removed from |
@@ -1268,25 +1135,35 @@ EXPORT_SYMBOL_GPL(eeh_add_device_tree_late); | |||
1268 | */ | 1135 | */ |
1269 | static void eeh_remove_device(struct pci_dev *dev) | 1136 | static void eeh_remove_device(struct pci_dev *dev) |
1270 | { | 1137 | { |
1271 | struct device_node *dn; | 1138 | struct eeh_dev *edev; |
1139 | |||
1272 | if (!dev || !eeh_subsystem_enabled) | 1140 | if (!dev || !eeh_subsystem_enabled) |
1273 | return; | 1141 | return; |
1142 | edev = pci_dev_to_eeh_dev(dev); | ||
1274 | 1143 | ||
1275 | /* Unregister the device with the EEH/PCI address search system */ | 1144 | /* Unregister the device with the EEH/PCI address search system */ |
1276 | pr_debug("EEH: Removing device %s\n", pci_name(dev)); | 1145 | pr_debug("EEH: Removing device %s\n", pci_name(dev)); |
1277 | 1146 | ||
1278 | dn = pci_device_to_OF_node(dev); | 1147 | if (!edev || !edev->pdev) { |
1279 | if (PCI_DN(dn)->pcidev == NULL) { | ||
1280 | pr_debug("EEH: Not referenced !\n"); | 1148 | pr_debug("EEH: Not referenced !\n"); |
1281 | return; | 1149 | return; |
1282 | } | 1150 | } |
1283 | PCI_DN(dn)->pcidev = NULL; | 1151 | edev->pdev = NULL; |
1284 | pci_dev_put (dev); | 1152 | dev->dev.archdata.edev = NULL; |
1153 | pci_dev_put(dev); | ||
1285 | 1154 | ||
1286 | pci_addr_cache_remove_device(dev); | 1155 | pci_addr_cache_remove_device(dev); |
1287 | eeh_sysfs_remove_device(dev); | 1156 | eeh_sysfs_remove_device(dev); |
1288 | } | 1157 | } |
1289 | 1158 | ||
1159 | /** | ||
1160 | * eeh_remove_bus_device - Undo EEH setup for the indicated PCI device | ||
1161 | * @dev: PCI device | ||
1162 | * | ||
1163 | * This routine must be called when a device is removed from the | ||
1164 | * running system through hotplug or dlpar. The corresponding | ||
1165 | * PCI address cache will be removed. | ||
1166 | */ | ||
1290 | void eeh_remove_bus_device(struct pci_dev *dev) | 1167 | void eeh_remove_bus_device(struct pci_dev *dev) |
1291 | { | 1168 | { |
1292 | struct pci_bus *bus = dev->subordinate; | 1169 | struct pci_bus *bus = dev->subordinate; |
@@ -1305,21 +1182,24 @@ static int proc_eeh_show(struct seq_file *m, void *v) | |||
1305 | { | 1182 | { |
1306 | if (0 == eeh_subsystem_enabled) { | 1183 | if (0 == eeh_subsystem_enabled) { |
1307 | seq_printf(m, "EEH Subsystem is globally disabled\n"); | 1184 | seq_printf(m, "EEH Subsystem is globally disabled\n"); |
1308 | seq_printf(m, "eeh_total_mmio_ffs=%ld\n", total_mmio_ffs); | 1185 | seq_printf(m, "eeh_total_mmio_ffs=%llu\n", eeh_stats.total_mmio_ffs); |
1309 | } else { | 1186 | } else { |
1310 | seq_printf(m, "EEH Subsystem is enabled\n"); | 1187 | seq_printf(m, "EEH Subsystem is enabled\n"); |
1311 | seq_printf(m, | 1188 | seq_printf(m, |
1312 | "no device=%ld\n" | 1189 | "no device=%llu\n" |
1313 | "no device node=%ld\n" | 1190 | "no device node=%llu\n" |
1314 | "no config address=%ld\n" | 1191 | "no config address=%llu\n" |
1315 | "check not wanted=%ld\n" | 1192 | "check not wanted=%llu\n" |
1316 | "eeh_total_mmio_ffs=%ld\n" | 1193 | "eeh_total_mmio_ffs=%llu\n" |
1317 | "eeh_false_positives=%ld\n" | 1194 | "eeh_false_positives=%llu\n" |
1318 | "eeh_slot_resets=%ld\n", | 1195 | "eeh_slot_resets=%llu\n", |
1319 | no_device, no_dn, no_cfg_addr, | 1196 | eeh_stats.no_device, |
1320 | ignored_check, total_mmio_ffs, | 1197 | eeh_stats.no_dn, |
1321 | false_positives, | 1198 | eeh_stats.no_cfg_addr, |
1322 | slot_resets); | 1199 | eeh_stats.ignored_check, |
1200 | eeh_stats.total_mmio_ffs, | ||
1201 | eeh_stats.false_positives, | ||
1202 | eeh_stats.slot_resets); | ||
1323 | } | 1203 | } |
1324 | 1204 | ||
1325 | return 0; | 1205 | return 0; |