eeh.c 34.8 KB
Newer Older
L
Linus Torvalds 已提交
1
/*
2 3 4
 * Copyright IBM Corporation 2001, 2005, 2006
 * Copyright Dave Engebretsen & Todd Inglett 2001
 * Copyright Linas Vepstas 2005, 2006
5
 * Copyright 2001-2012 IBM Corporation.
L
Linas Vepstas 已提交
6
 *
L
Linus Torvalds 已提交
7 8 9 10
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
L
Linas Vepstas 已提交
11
 *
L
Linus Torvalds 已提交
12 13 14 15
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
L
Linas Vepstas 已提交
16
 *
L
Linus Torvalds 已提交
17 18 19
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
20 21
 *
 * Please address comments and feedback to Linas Vepstas <linas@austin.ibm.com>
L
Linus Torvalds 已提交
22 23
 */

24
#include <linux/delay.h>
25
#include <linux/sched.h>
L
Linus Torvalds 已提交
26 27 28 29 30 31 32
#include <linux/init.h>
#include <linux/list.h>
#include <linux/pci.h>
#include <linux/proc_fs.h>
#include <linux/rbtree.h>
#include <linux/seq_file.h>
#include <linux/spinlock.h>
33
#include <linux/export.h>
34 35
#include <linux/of.h>

A
Arun Sharma 已提交
36
#include <linux/atomic.h>
L
Linus Torvalds 已提交
37
#include <asm/eeh.h>
38
#include <asm/eeh_event.h>
L
Linus Torvalds 已提交
39 40
#include <asm/io.h>
#include <asm/machdep.h>
41
#include <asm/ppc-pci.h>
L
Linus Torvalds 已提交
42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
#include <asm/rtas.h>


/** Overview:
 *  EEH, or "Extended Error Handling" is a PCI bridge technology for
 *  dealing with PCI bus errors that can't be dealt with within the
 *  usual PCI framework, except by check-stopping the CPU.  Systems
 *  that are designed for high-availability/reliability cannot afford
 *  to crash due to a "mere" PCI error, thus the need for EEH.
 *  An EEH-capable bridge operates by converting a detected error
 *  into a "slot freeze", taking the PCI adapter off-line, making
 *  the slot behave, from the OS'es point of view, as if the slot
 *  were "empty": all reads return 0xff's and all writes are silently
 *  ignored.  EEH slot isolation events can be triggered by parity
 *  errors on the address or data busses (e.g. during posted writes),
L
Linas Vepstas 已提交
57 58
 *  which in turn might be caused by low voltage on the bus, dust,
 *  vibration, humidity, radioactivity or plain-old failed hardware.
L
Linus Torvalds 已提交
59 60 61 62 63 64 65 66 67 68 69
 *
 *  Note, however, that one of the leading causes of EEH slot
 *  freeze events are buggy device drivers, buggy device microcode,
 *  or buggy device hardware.  This is because any attempt by the
 *  device to bus-master data to a memory address that is not
 *  assigned to the device will trigger a slot freeze.   (The idea
 *  is to prevent devices-gone-wild from corrupting system memory).
 *  Buggy hardware/drivers will have a miserable time co-existing
 *  with EEH.
 *
 *  Ideally, a PCI device driver, when suspecting that an isolation
L
Lucas De Marchi 已提交
70
 *  event has occurred (e.g. by reading 0xff's), will then ask EEH
L
Linus Torvalds 已提交
71 72 73 74 75 76 77 78
 *  whether this is the case, and then take appropriate steps to
 *  reset the PCI slot, the PCI device, and then resume operations.
 *  However, until that day,  the checking is done here, with the
 *  eeh_check_failure() routine embedded in the MMIO macros.  If
 *  the slot is found to be isolated, an "EEH Event" is synthesized
 *  and sent out for processing.
 */

79
/* If a device driver keeps reading an MMIO register in an interrupt
80 81 82
 * handler after a slot isolation event, it might be broken.
 * This sets the threshold for how many read attempts we allow
 * before printing an error message.
L
Linus Torvalds 已提交
83
 */
84
#define EEH_MAX_FAILS	2100000
L
Linus Torvalds 已提交
85

86
/* Time to wait for a PCI slot to report status, in milliseconds */
87 88
#define PCI_BUS_RESET_WAIT_MSEC (60*1000)

L
Linus Torvalds 已提交
89
/* RTAS tokens */
90
static int ibm_configure_bridge;
91
static int ibm_configure_pe;
L
Linus Torvalds 已提交
92

93 94 95
/* Platform dependent EEH operations */
struct eeh_ops *eeh_ops = NULL;

96 97
int eeh_subsystem_enabled;
EXPORT_SYMBOL(eeh_subsystem_enabled);
L
Linus Torvalds 已提交
98

99
/* Lock to avoid races due to multiple reports of an error */
100
static DEFINE_RAW_SPINLOCK(confirm_error_lock);
101

102 103 104 105
/* Buffer for reporting pci register dumps. Its here in BSS, and
 * not dynamically alloced, so that it ends up in RMO where RTAS
 * can access it.
 */
106 107 108
#define EEH_PCI_REGS_LOG_LEN 4096
static unsigned char pci_regs_buf[EEH_PCI_REGS_LOG_LEN];

L
Linus Torvalds 已提交
109
/* System monitoring statistics */
110 111 112 113 114 115 116
static unsigned long no_device;
static unsigned long no_dn;
static unsigned long no_cfg_addr;
static unsigned long ignored_check;
static unsigned long total_mmio_ffs;
static unsigned long false_positives;
static unsigned long slot_resets;
L
Linus Torvalds 已提交
117

118 119
#define IS_BRIDGE(class_code) (((class_code)<<16) == PCI_BASE_CLASS_BRIDGE)

120
/**
121
 * eeh_gather_pci_data - Copy assorted PCI config space registers to buff
122 123 124 125 126 127 128
 * @pdn: device to report data for
 * @buf: point to buffer in which to log
 * @len: amount of room in buffer
 *
 * This routine captures assorted PCI configuration space data,
 * and puts them into a buffer for RTAS error logging.
 */
129
static size_t eeh_gather_pci_data(struct pci_dn *pdn, char * buf, size_t len)
130
{
131
	struct pci_dev *dev = pdn->pcidev;
132
	u32 cfg;
133
	int cap, i;
134 135
	int n = 0;

136 137 138
	n += scnprintf(buf+n, len-n, "%s\n", pdn->node->full_name);
	printk(KERN_WARNING "EEH: of node=%s\n", pdn->node->full_name);

139
	rtas_read_config(pdn, PCI_VENDOR_ID, 4, &cfg);
140 141 142
	n += scnprintf(buf+n, len-n, "dev/vend:%08x\n", cfg);
	printk(KERN_WARNING "EEH: PCI device/vendor: %08x\n", cfg);

143 144
	rtas_read_config(pdn, PCI_COMMAND, 4, &cfg);
	n += scnprintf(buf+n, len-n, "cmd/stat:%x\n", cfg);
145 146
	printk(KERN_WARNING "EEH: PCI cmd/status register: %08x\n", cfg);

147 148 149 150 151
	if (!dev) {
		printk(KERN_WARNING "EEH: no PCI device for this of node\n");
		return n;
	}

152 153 154 155 156 157 158 159 160 161 162
	/* Gather bridge-specific registers */
	if (dev->class >> 16 == PCI_BASE_CLASS_BRIDGE) {
		rtas_read_config(pdn, PCI_SEC_STATUS, 2, &cfg);
		n += scnprintf(buf+n, len-n, "sec stat:%x\n", cfg);
		printk(KERN_WARNING "EEH: Bridge secondary status: %04x\n", cfg);

		rtas_read_config(pdn, PCI_BRIDGE_CONTROL, 2, &cfg);
		n += scnprintf(buf+n, len-n, "brdg ctl:%x\n", cfg);
		printk(KERN_WARNING "EEH: Bridge control: %04x\n", cfg);
	}

163
	/* Dump out the PCI-X command and status regs */
164
	cap = pci_find_capability(dev, PCI_CAP_ID_PCIX);
165 166 167 168 169 170 171 172 173 174 175
	if (cap) {
		rtas_read_config(pdn, cap, 4, &cfg);
		n += scnprintf(buf+n, len-n, "pcix-cmd:%x\n", cfg);
		printk(KERN_WARNING "EEH: PCI-X cmd: %08x\n", cfg);

		rtas_read_config(pdn, cap+4, 4, &cfg);
		n += scnprintf(buf+n, len-n, "pcix-stat:%x\n", cfg);
		printk(KERN_WARNING "EEH: PCI-X status: %08x\n", cfg);
	}

	/* If PCI-E capable, dump PCI-E cap 10, and the AER */
176
	cap = pci_find_capability(dev, PCI_CAP_ID_EXP);
177 178 179 180 181 182 183 184 185 186 187
	if (cap) {
		n += scnprintf(buf+n, len-n, "pci-e cap10:\n");
		printk(KERN_WARNING
		       "EEH: PCI-E capabilities and status follow:\n");

		for (i=0; i<=8; i++) {
			rtas_read_config(pdn, cap+4*i, 4, &cfg);
			n += scnprintf(buf+n, len-n, "%02x:%x\n", 4*i, cfg);
			printk(KERN_WARNING "EEH: PCI-E %02x: %08x\n", i, cfg);
		}

188
		cap = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR);
189 190 191 192 193 194 195 196 197 198 199 200
		if (cap) {
			n += scnprintf(buf+n, len-n, "pci-e AER:\n");
			printk(KERN_WARNING
			       "EEH: PCI-E AER capability register set follows:\n");

			for (i=0; i<14; i++) {
				rtas_read_config(pdn, cap+4*i, 4, &cfg);
				n += scnprintf(buf+n, len-n, "%02x:%x\n", 4*i, cfg);
				printk(KERN_WARNING "EEH: PCI-E AER %02x: %08x\n", i, cfg);
			}
		}
	}
201 202 203

	/* Gather status on devices under the bridge */
	if (dev->class >> 16 == PCI_BASE_CLASS_BRIDGE) {
204 205 206
		struct device_node *dn;

		for_each_child_of_node(pdn->node, dn) {
207 208
			pdn = PCI_DN(dn);
			if (pdn)
209
				n += eeh_gather_pci_data(pdn, buf+n, len-n);
210 211 212
		}
	}

213 214 215
	return n;
}

216 217 218 219 220 221 222 223 224 225
/**
 * eeh_slot_error_detail - Generate combined log including driver log and error log
 * @pdn: device node
 * @severity: temporary or permanent error log
 *
 * This routine should be called to generate the combined log, which
 * is comprised of driver log and error log. The driver log is figured
 * out from the config space of the corresponding PCI device, while
 * the error log is fetched through platform dependent function call.
 */
226 227 228
void eeh_slot_error_detail(struct pci_dn *pdn, int severity)
{
	size_t loglen = 0;
229
	pci_regs_buf[0] = 0;
230

231
	eeh_pci_enable(pdn, EEH_OPT_THAW_MMIO);
232
	eeh_configure_bridge(pdn);
233
	eeh_restore_bars(pdn);
234
	loglen = eeh_gather_pci_data(pdn, pci_regs_buf, EEH_PCI_REGS_LOG_LEN);
235

236
	eeh_ops->get_log(pdn->node, severity, pci_regs_buf, loglen);
237 238
}

L
Linus Torvalds 已提交
239
/**
240 241 242 243 244
 * eeh_token_to_phys - Convert EEH address token to phys address
 * @token: I/O token, should be address in the form 0xA....
 *
 * This routine should be called to convert virtual I/O address
 * to physical one.
L
Linus Torvalds 已提交
245 246 247 248 249 250
 */
static inline unsigned long eeh_token_to_phys(unsigned long token)
{
	pte_t *ptep;
	unsigned long pa;

D
David Gibson 已提交
251
	ptep = find_linux_pte(init_mm.pgd, token);
L
Linus Torvalds 已提交
252 253 254 255 256 257 258
	if (!ptep)
		return token;
	pa = pte_pfn(*ptep) << PAGE_SHIFT;

	return pa | (token & (PAGE_SIZE-1));
}

259
/**
260
 * eeh_find_device_pe - Retrieve the PE for the given device
261 262 263
 * @dn: device node
 *
 * Return the PE under which this device lies
264
 */
265
struct device_node *eeh_find_device_pe(struct device_node *dn)
266 267 268 269 270 271 272 273
{
	while ((dn->parent) && PCI_DN(dn->parent) &&
	      (PCI_DN(dn->parent)->eeh_mode & EEH_MODE_SUPPORTED)) {
		dn = dn->parent;
	}
	return dn;
}

274 275 276 277 278 279 280 281 282 283 284
/**
 * __eeh_mark_slot - Mark all child devices as failed
 * @parent: parent device
 * @mode_flag: failure flag
 *
 * Mark all devices that are children of this device as failed.
 * Mark the device driver too, so that it can see the failure
 * immediately; this is critical, since some drivers poll
 * status registers in interrupts ... If a driver is polling,
 * and the slot is frozen, then the driver can deadlock in
 * an interrupt context, which is bad.
285
 */
286
static void __eeh_mark_slot(struct device_node *parent, int mode_flag)
287
{
288 289 290
	struct device_node *dn;

	for_each_child_of_node(parent, dn) {
L
Linas Vepstas 已提交
291
		if (PCI_DN(dn)) {
292 293
			/* Mark the pci device driver too */
			struct pci_dev *dev = PCI_DN(dn)->pcidev;
294 295 296

			PCI_DN(dn)->eeh_mode |= mode_flag;

297 298 299
			if (dev && dev->driver)
				dev->error_state = pci_channel_io_frozen;

300
			__eeh_mark_slot(dn, mode_flag);
L
Linas Vepstas 已提交
301
		}
302 303 304
	}
}

305 306 307 308 309 310 311 312 313
/**
 * eeh_mark_slot - Mark the indicated device and its children as failed
 * @dn: parent device
 * @mode_flag: failure flag
 *
 * Mark the indicated device and its child devices as failed.
 * The device drivers are marked as failed as well.
 */
void eeh_mark_slot(struct device_node *dn, int mode_flag)
L
Linas Vepstas 已提交
314
{
315
	struct pci_dev *dev;
316
	dn = eeh_find_device_pe(dn);
317 318

	/* Back up one, since config addrs might be shared */
319
	if (!pcibios_find_pci_bus(dn) && PCI_DN(dn->parent))
320 321
		dn = dn->parent;

L
Linas Vepstas 已提交
322
	PCI_DN(dn)->eeh_mode |= mode_flag;
323 324 325 326 327 328

	/* Mark the pci device too */
	dev = PCI_DN(dn)->pcidev;
	if (dev)
		dev->error_state = pci_channel_io_frozen;

329
	__eeh_mark_slot(dn, mode_flag);
L
Linas Vepstas 已提交
330 331
}

332 333 334 335 336 337 338
/**
 * __eeh_clear_slot - Clear failure flag for the child devices
 * @parent: parent device
 * @mode_flag: flag to be cleared
 *
 * Clear failure flag for the child devices.
 */
339
static void __eeh_clear_slot(struct device_node *parent, int mode_flag)
340
{
341 342 343
	struct device_node *dn;

	for_each_child_of_node(parent, dn) {
L
Linas Vepstas 已提交
344 345 346
		if (PCI_DN(dn)) {
			PCI_DN(dn)->eeh_mode &= ~mode_flag;
			PCI_DN(dn)->eeh_check_count = 0;
347
			__eeh_clear_slot(dn, mode_flag);
L
Linas Vepstas 已提交
348
		}
349 350 351
	}
}

352 353 354 355 356 357 358 359
/**
 * eeh_clear_slot - Clear failure flag for the indicated device and its children
 * @dn: parent device
 * @mode_flag: flag to be cleared
 *
 * Clear failure flag for the indicated device and its children.
 */
void eeh_clear_slot(struct device_node *dn, int mode_flag)
360 361
{
	unsigned long flags;
362
	raw_spin_lock_irqsave(&confirm_error_lock, flags);
363
	
364
	dn = eeh_find_device_pe(dn);
365 366
	
	/* Back up one, since config addrs might be shared */
367
	if (!pcibios_find_pci_bus(dn) && PCI_DN(dn->parent))
368 369
		dn = dn->parent;

L
Linas Vepstas 已提交
370 371
	PCI_DN(dn)->eeh_mode &= ~mode_flag;
	PCI_DN(dn)->eeh_check_count = 0;
372
	__eeh_clear_slot(dn, mode_flag);
373
	raw_spin_unlock_irqrestore(&confirm_error_lock, flags);
374 375
}

L
Linus Torvalds 已提交
376
/**
377 378 379
 * eeh_dn_check_failure - Check if all 1's data is due to EEH slot freeze
 * @dn: device node
 * @dev: pci device, if known
L
Linus Torvalds 已提交
380 381 382 383 384 385 386
 *
 * Check for an EEH failure for the given device node.  Call this
 * routine if the result of a read was all 0xff's and you want to
 * find out if this is due to an EEH slot freeze.  This routine
 * will query firmware for the EEH status.
 *
 * Returns 0 if there has not been an EEH error; otherwise returns
L
Linas Vepstas 已提交
387
 * a non-zero value and queues up a slot isolation event notification.
L
Linus Torvalds 已提交
388 389 390 391 392 393 394
 *
 * It is safe to call this routine in an interrupt context.
 */
int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev)
{
	int ret;
	unsigned long flags;
395
	struct pci_dn *pdn;
396
	int rc = 0;
397
	const char *location;
L
Linus Torvalds 已提交
398

399
	total_mmio_ffs++;
L
Linus Torvalds 已提交
400 401 402 403

	if (!eeh_subsystem_enabled)
		return 0;

404
	if (!dn) {
405
		no_dn++;
L
Linus Torvalds 已提交
406
		return 0;
407
	}
408
	dn = eeh_find_device_pe(dn);
L
Linas Vepstas 已提交
409
	pdn = PCI_DN(dn);
L
Linus Torvalds 已提交
410 411

	/* Access to IO BARs might get this far and still not want checking. */
412
	if (!(pdn->eeh_mode & EEH_MODE_SUPPORTED) ||
413
	    pdn->eeh_mode & EEH_MODE_NOCHECK) {
414
		ignored_check++;
415
		pr_debug("EEH: Ignored check (%x) for %s %s\n",
416
			 pdn->eeh_mode, eeh_pci_name(dev), dn->full_name);
L
Linus Torvalds 已提交
417 418 419
		return 0;
	}

420
	if (!pdn->eeh_config_addr && !pdn->eeh_pe_config_addr) {
421
		no_cfg_addr++;
L
Linus Torvalds 已提交
422 423 424
		return 0;
	}

425 426 427 428 429
	/* If we already have a pending isolation event for this
	 * slot, we know it's bad already, we don't need to check.
	 * Do this checking under a lock; as multiple PCI devices
	 * in one slot might report errors simultaneously, and we
	 * only want one error recovery routine running.
L
Linus Torvalds 已提交
430
	 */
431
	raw_spin_lock_irqsave(&confirm_error_lock, flags);
432
	rc = 1;
433
	if (pdn->eeh_mode & EEH_MODE_ISOLATED) {
434
		pdn->eeh_check_count ++;
435 436
		if (pdn->eeh_check_count % EEH_MAX_FAILS == 0) {
			location = of_get_property(dn, "ibm,loc-code", NULL);
437
			printk(KERN_ERR "EEH: %d reads ignored for recovering device at "
438 439
				"location=%s driver=%s pci addr=%s\n",
				pdn->eeh_check_count, location,
440
				eeh_driver_name(dev), eeh_pci_name(dev));
441
			printk(KERN_ERR "EEH: Might be infinite loop in %s driver\n",
442
				eeh_driver_name(dev));
443
			dump_stack();
L
Linus Torvalds 已提交
444
		}
445
		goto dn_unlock;
L
Linus Torvalds 已提交
446 447 448 449 450 451 452 453 454
	}

	/*
	 * Now test for an EEH failure.  This is VERY expensive.
	 * Note that the eeh_config_addr may be a parent device
	 * in the case of a device behind a bridge, or it may be
	 * function zero of a multi-function device.
	 * In any case they must share a common PHB.
	 */
455
	ret = eeh_ops->get_state(pdn->node, NULL);
456

457
	/* Note that config-io to empty slots may fail;
458
	 * they are empty when they don't have children.
459 460 461
	 * We will punt with the following conditions: Failure to get
	 * PE's state, EEH not support and Permanently unavailable
	 * state, PE is in good state.
462
	 */
463 464 465 466
	if ((ret < 0) ||
	    (ret == EEH_STATE_NOT_SUPPORT) ||
	    (ret & (EEH_STATE_MMIO_ACTIVE | EEH_STATE_DMA_ACTIVE)) ==
	    (EEH_STATE_MMIO_ACTIVE | EEH_STATE_DMA_ACTIVE)) {
467
		false_positives++;
468
		pdn->eeh_false_positives ++;
469 470
		rc = 0;
		goto dn_unlock;
471 472
	}

473
	slot_resets++;
474 475 476
 
	/* Avoid repeated reports of this failure, including problems
	 * with other functions on this device, and functions under
477 478 479
	 * bridges.
	 */
	eeh_mark_slot(dn, EEH_MODE_ISOLATED);
480
	raw_spin_unlock_irqrestore(&confirm_error_lock, flags);
L
Linus Torvalds 已提交
481

482
	eeh_send_failure_event(dn, dev);
483

L
Linus Torvalds 已提交
484 485
	/* Most EEH events are due to device driver bugs.  Having
	 * a stack trace will help the device-driver authors figure
486 487
	 * out what happened.  So print that out.
	 */
488
	dump_stack();
489 490 491
	return 1;

dn_unlock:
492
	raw_spin_unlock_irqrestore(&confirm_error_lock, flags);
493
	return rc;
L
Linus Torvalds 已提交
494 495
}

496
EXPORT_SYMBOL_GPL(eeh_dn_check_failure);
L
Linus Torvalds 已提交
497 498

/**
499 500 501
 * eeh_check_failure - Check if all 1's data is due to EEH slot freeze
 * @token: I/O token, should be address in the form 0xA....
 * @val: value, should be all 1's (XXX why do we need this arg??)
L
Linus Torvalds 已提交
502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518
 *
 * Check for an EEH failure at the given token address.  Call this
 * routine if the result of a read was all 0xff's and you want to
 * find out if this is due to an EEH slot freeze event.  This routine
 * will query firmware for the EEH status.
 *
 * Note this routine is safe to call in an interrupt context.
 */
unsigned long eeh_check_failure(const volatile void __iomem *token, unsigned long val)
{
	unsigned long addr;
	struct pci_dev *dev;
	struct device_node *dn;

	/* Finding the phys addr + pci device; this is pretty quick. */
	addr = eeh_token_to_phys((unsigned long __force) token);
	dev = pci_get_device_by_addr(addr);
519
	if (!dev) {
520
		no_device++;
L
Linus Torvalds 已提交
521
		return val;
522
	}
L
Linus Torvalds 已提交
523 524

	dn = pci_device_to_OF_node(dev);
525
	eeh_dn_check_failure(dn, dev);
L
Linus Torvalds 已提交
526 527 528 529 530 531 532

	pci_dev_put(dev);
	return val;
}

EXPORT_SYMBOL(eeh_check_failure);

533

534
/**
535
 * eeh_pci_enable - Enable MMIO or DMA transfers for this slot
536
 * @pdn pci device node
537 538 539 540
 *
 * This routine should be called to reenable frozen MMIO or DMA
 * so that it would work correctly again. It's useful while doing
 * recovery or log collection on the indicated device.
541
 */
542
int eeh_pci_enable(struct pci_dn *pdn, int function)
543 544 545
{
	int rc;

546
	rc = eeh_ops->set_option(pdn->node, function);
547
	if (rc)
548
		printk(KERN_WARNING "EEH: Unexpected state change %d, err=%d dn=%s\n",
549 550
		        function, rc, pdn->node->full_name);

551
	rc = eeh_ops->wait_state(pdn->node, PCI_BUS_RESET_WAIT_MSEC);
552 553
	if (rc > 0 && (rc & EEH_STATE_MMIO_ENABLED) &&
	   (function == EEH_OPT_THAW_MMIO))
554 555
		return 0;

556 557 558
	return rc;
}

559 560
/**
 * pcibios_set_pcie_slot_reset - Set PCI-E reset state
561 562
 * @dev: pci device struct
 * @state: reset state to enter
563 564 565
 *
 * Return value:
 * 	0 if success
566
 */
567 568 569 570 571 572
int pcibios_set_pcie_reset_state(struct pci_dev *dev, enum pcie_reset_state state)
{
	struct device_node *dn = pci_device_to_OF_node(dev);

	switch (state) {
	case pcie_deassert_reset:
573
		eeh_ops->reset(dn, EEH_RESET_DEACTIVATE);
574 575
		break;
	case pcie_hot_reset:
576
		eeh_ops->reset(dn, EEH_RESET_HOT);
577 578
		break;
	case pcie_warm_reset:
579
		eeh_ops->reset(dn, EEH_RESET_FUNDAMENTAL);
580 581 582 583 584 585 586 587
		break;
	default:
		return -EINVAL;
	};

	return 0;
}

588
/**
589 590 591 592 593 594 595
 * __eeh_set_pe_freset - Check the required reset for child devices
 * @parent: parent device
 * @freset: return value
 *
 * Each device might have its preferred reset type: fundamental or
 * hot reset. The routine is used to collect the information from
 * the child devices so that they could be reset accordingly.
596
 */
597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625
void __eeh_set_pe_freset(struct device_node *parent, unsigned int *freset)
{
	struct device_node *dn;

	for_each_child_of_node(parent, dn) {
		if (PCI_DN(dn)) {
			struct pci_dev *dev = PCI_DN(dn)->pcidev;

			if (dev && dev->driver)
				*freset |= dev->needs_freset;

			__eeh_set_pe_freset(dn, freset);
		}
	}
}

/**
 * eeh_set_pe_freset - Check the required reset for the indicated device and its children
 * @dn: parent device
 * @freset: return value
 *
 * Each device might have its preferred reset type: fundamental or
 * hot reset. The routine is used to collected the information for
 * the indicated device and its children so that the bunch of the
 * devices could be reset properly.
 */
void eeh_set_pe_freset(struct device_node *dn, unsigned int *freset)
{
	struct pci_dev *dev;
626
	dn = eeh_find_device_pe(dn);
627 628 629 630

	/* Back up one, since config addrs might be shared */
	if (!pcibios_find_pci_bus(dn) && PCI_DN(dn->parent))
		dn = dn->parent;
631

632 633 634 635 636 637 638 639
	dev = PCI_DN(dn)->pcidev;
	if (dev)
		*freset |= dev->needs_freset;

	__eeh_set_pe_freset(dn, freset);
}

/**
640
 * eeh_reset_pe_once - Assert the pci #RST line for 1/4 second
641 642 643 644
 * @pdn: pci device node to be reset.
 *
 * Assert the PCI #RST line for 1/4 second.
 */
645
static void eeh_reset_pe_once(struct pci_dn *pdn)
646
{
647
	unsigned int freset = 0;
648

649 650 651 652 653 654 655 656 657
	/* Determine type of EEH reset required for
	 * Partitionable Endpoint, a hot-reset (1)
	 * or a fundamental reset (3).
	 * A fundamental reset required by any device under
	 * Partitionable Endpoint trumps hot-reset.
  	 */
	eeh_set_pe_freset(pdn->node, &freset);

	if (freset)
658
		eeh_ops->reset(pdn->node, EEH_RESET_FUNDAMENTAL);
659
	else
660
		eeh_ops->reset(pdn->node, EEH_RESET_HOT);
661 662

	/* The PCI bus requires that the reset be held high for at least
663 664
	 * a 100 milliseconds. We wait a bit longer 'just in case'.
	 */
665
#define PCI_BUS_RST_HOLD_TIME_MSEC 250
666
	msleep(PCI_BUS_RST_HOLD_TIME_MSEC);
L
Linas Vepstas 已提交
667 668 669
	
	/* We might get hit with another EEH freeze as soon as the 
	 * pci slot reset line is dropped. Make sure we don't miss
670 671 672
	 * these, and clear the flag now.
	 */
	eeh_clear_slot(pdn->node, EEH_MODE_ISOLATED);
L
Linas Vepstas 已提交
673

674
	eeh_ops->reset(pdn->node, EEH_RESET_DEACTIVATE);
675 676 677

	/* After a PCI slot has been reset, the PCI Express spec requires
	 * a 1.5 second idle time for the bus to stabilize, before starting
678 679
	 * up traffic.
	 */
680
#define PCI_BUS_SETTLE_TIME_MSEC 1800
681
	msleep(PCI_BUS_SETTLE_TIME_MSEC);
682 683
}

684
/**
685
 * eeh_reset_pe - Reset the indicated PE
686 687 688 689 690 691
 * @pdn: PCI device node
 *
 * This routine should be called to reset indicated device, including
 * PE. A PE might include multiple PCI devices and sometimes PCI bridges
 * might be involved as well.
 */
692
int eeh_reset_pe(struct pci_dn *pdn)
693 694 695
{
	int i, rc;

696 697
	/* Take three shots at resetting the bus */
	for (i=0; i<3; i++) {
698
		eeh_reset_pe_once(pdn);
699

700
		rc = eeh_ops->wait_state(pdn->node, PCI_BUS_RESET_WAIT_MSEC);
701
		if (rc == (EEH_STATE_MMIO_ACTIVE | EEH_STATE_DMA_ACTIVE))
702
			return 0;
703 704

		if (rc < 0) {
705 706
			printk(KERN_ERR "EEH: unrecoverable slot failure %s\n",
			       pdn->node->full_name);
707
			return -1;
708
		}
709 710
		printk(KERN_ERR "EEH: bus reset %d failed on slot %s, rc=%d\n",
		       i+1, pdn->node->full_name, rc);
711
	}
712

713
	return -1;
714 715
}

716 717 718 719 720 721 722 723 724
/** Save and restore of PCI BARs
 *
 * Although firmware will set up BARs during boot, it doesn't
 * set up device BAR's after a device reset, although it will,
 * if requested, set up bridge configuration. Thus, we need to
 * configure the PCI devices ourselves.  
 */

/**
725
 * eeh_restore_one_device_bars - Restore the Base Address Registers for one device
726 727
 * @pdn: pci device node
 *
728 729 730 731
 * Loads the PCI configuration space base address registers,
 * the expansion ROM base address, the latency timer, and etc.
 * from the saved values in the device node.
 */
732
static inline void eeh_restore_one_device_bars(struct pci_dn *pdn)
733 734
{
	int i;
735
	u32 cmd;
736 737 738 739 740 741 742 743 744 745 746 747

	if (NULL==pdn->phb) return;
	for (i=4; i<10; i++) {
		rtas_write_config(pdn, i*4, 4, pdn->config_space[i]);
	}

	/* 12 == Expansion ROM Address */
	rtas_write_config(pdn, 12*4, 4, pdn->config_space[12]);

#define BYTE_SWAP(OFF) (8*((OFF)/4)+3-(OFF))
#define SAVED_BYTE(OFF) (((u8 *)(pdn->config_space))[BYTE_SWAP(OFF)])

748
	rtas_write_config(pdn, PCI_CACHE_LINE_SIZE, 1,
749 750
	            SAVED_BYTE(PCI_CACHE_LINE_SIZE));

751
	rtas_write_config(pdn, PCI_LATENCY_TIMER, 1,
752 753 754 755
	            SAVED_BYTE(PCI_LATENCY_TIMER));

	/* max latency, min grant, interrupt pin and line */
	rtas_write_config(pdn, 15*4, 4, pdn->config_space[15]);
756 757

	/* Restore PERR & SERR bits, some devices require it,
758 759
	 * don't touch the other command bits
	 */
760 761 762 763 764 765 766 767 768 769
	rtas_read_config(pdn, PCI_COMMAND, 4, &cmd);
	if (pdn->config_space[1] & PCI_COMMAND_PARITY)
		cmd |= PCI_COMMAND_PARITY;
	else
		cmd &= ~PCI_COMMAND_PARITY;
	if (pdn->config_space[1] & PCI_COMMAND_SERR)
		cmd |= PCI_COMMAND_SERR;
	else
		cmd &= ~PCI_COMMAND_SERR;
	rtas_write_config(pdn, PCI_COMMAND, 4, cmd);
770 771 772
}

/**
773 774
 * eeh_restore_bars - Restore the PCI config space info
 * @pdn: PCI device node
775 776 777 778 779 780 781 782 783 784
 *
 * This routine performs a recursive walk to the children
 * of this device as well.
 */
void eeh_restore_bars(struct pci_dn *pdn)
{
	struct device_node *dn;
	if (!pdn) 
		return;
	
785
	if ((pdn->eeh_mode & EEH_MODE_SUPPORTED) && !IS_BRIDGE(pdn->class_code))
786
		eeh_restore_one_device_bars(pdn);
787

788
	for_each_child_of_node(pdn->node, dn)
789
		eeh_restore_bars(PCI_DN(dn));
790 791 792
}

/**
793 794
 * eeh_save_bars - Save device bars
 * @pdn: PCI device node
795 796 797
 *
 * Save the values of the device bars. Unlike the restore
 * routine, this routine is *not* recursive. This is because
798
 * PCI devices are added individually; but, for the restore,
799 800
 * an entire slot is reset at a time.
 */
801
static void eeh_save_bars(struct pci_dn *pdn)
802 803 804
{
	int i;

805
	if (!pdn )
806 807 808
		return;
	
	for (i = 0; i < 16; i++)
809
		rtas_read_config(pdn, i * 4, 4, &pdn->config_space[i]);
810 811
}

812
/**
813
 * eeh_configure_bridge - Configure PCI bridges for the indicated PE
814 815 816 817 818 819
 * @pdn: PCI device node
 *
 * PCI bridges might be included in PE. In order to make the PE work
 * again. The included PCI bridges should be recovered after the PE
 * encounters frozen state.
 */
820
void eeh_configure_bridge(struct pci_dn *pdn)
821
{
822
	int config_addr;
823
	int rc;
824
	int token;
825

826 827 828 829 830
	/* Use PE configuration address, if present */
	config_addr = pdn->eeh_config_addr;
	if (pdn->eeh_pe_config_addr)
		config_addr = pdn->eeh_pe_config_addr;

831 832 833 834 835 836 837
	/* Use new configure-pe function, if supported */
	if (ibm_configure_pe != RTAS_UNKNOWN_SERVICE)
		token = ibm_configure_pe;
	else
		token = ibm_configure_bridge;

	rc = rtas_call(token, 3, 1, NULL,
838
	               config_addr,
839 840 841
	               BUID_HI(pdn->phb->buid),
	               BUID_LO(pdn->phb->buid));
	if (rc) {
842
		printk(KERN_WARNING "EEH: Unable to configure device bridge (%d) for %s\n",
843 844 845 846
		        rc, pdn->node->full_name);
	}
}

847
/**
848
 * eeh_early_enable - Early enable EEH on the indicated device
849 850 851 852 853 854 855
 * @dn: device node
 * @data: BUID
 *
 * Enable EEH functionality on the specified PCI device. The function
 * is expected to be called before real PCI probing is done. However,
 * the PHBs have been initialized at this point.
 */
856
static void *eeh_early_enable(struct device_node *dn, void *data)
L
Linus Torvalds 已提交
857 858
{
	int ret;
859 860 861
	const u32 *class_code = of_get_property(dn, "class-code", NULL);
	const u32 *vendor_id = of_get_property(dn, "vendor-id", NULL);
	const u32 *device_id = of_get_property(dn, "device-id", NULL);
862
	const u32 *regs;
L
Linus Torvalds 已提交
863
	int enable;
L
Linas Vepstas 已提交
864
	struct pci_dn *pdn = PCI_DN(dn);
L
Linus Torvalds 已提交
865

866
	pdn->class_code = 0;
867
	pdn->eeh_mode = 0;
868 869
	pdn->eeh_check_count = 0;
	pdn->eeh_freeze_count = 0;
870
	pdn->eeh_false_positives = 0;
L
Linus Torvalds 已提交
871

872 873
	if (!of_device_is_available(dn))
		return NULL;
L
Linus Torvalds 已提交
874 875 876 877 878 879 880

	/* Ignore bad nodes. */
	if (!class_code || !vendor_id || !device_id)
		return NULL;

	/* There is nothing to check on PCI to ISA bridges */
	if (dn->type && !strcmp(dn->type, "isa")) {
881
		pdn->eeh_mode |= EEH_MODE_NOCHECK;
L
Linus Torvalds 已提交
882 883
		return NULL;
	}
884
	pdn->class_code = *class_code;
L
Linus Torvalds 已提交
885 886

	/* Ok... see if this device supports EEH.  Some do, some don't,
887 888
	 * and the only way to find out is to check each and every one.
	 */
889
	regs = of_get_property(dn, "reg", NULL);
L
Linus Torvalds 已提交
890 891 892
	if (regs) {
		/* First register entry is addr (00BBSS00)  */
		/* Try to enable eeh */
893
		ret = eeh_ops->set_option(dn, EEH_OPT_ENABLE);
894

895
		enable = 0;
L
Linus Torvalds 已提交
896
		if (ret == 0) {
897
			pdn->eeh_config_addr = regs[0];
898 899

			/* If the newer, better, ibm,get-config-addr-info is supported, 
900 901
			 * then use that instead.
			 */
902
			pdn->eeh_pe_config_addr = eeh_ops->get_pe_addr(dn);
903 904 905 906

			/* Some older systems (Power4) allow the
			 * ibm,set-eeh-option call to succeed even on nodes
			 * where EEH is not supported. Verify support
907 908
			 * explicitly.
			 */
909 910
			ret = eeh_ops->get_state(pdn->node, NULL);
			if (ret > 0 && ret != EEH_STATE_NOT_SUPPORT)
911 912 913 914 915 916 917
				enable = 1;
		}

		if (enable) {
			eeh_subsystem_enabled = 1;
			pdn->eeh_mode |= EEH_MODE_SUPPORTED;

918 919 920
			pr_debug("EEH: %s: eeh enabled, config=%x pe_config=%x\n",
				 dn->full_name, pdn->eeh_config_addr,
				 pdn->eeh_pe_config_addr);
L
Linus Torvalds 已提交
921 922 923
		} else {

			/* This device doesn't support EEH, but it may have an
924 925
			 * EEH parent, in which case we mark it as supported.
			 */
L
Linas Vepstas 已提交
926
			if (dn->parent && PCI_DN(dn->parent)
927
			    && (PCI_DN(dn->parent)->eeh_mode & EEH_MODE_SUPPORTED)) {
L
Linus Torvalds 已提交
928
				/* Parent supports EEH. */
929 930
				pdn->eeh_mode |= EEH_MODE_SUPPORTED;
				pdn->eeh_config_addr = PCI_DN(dn->parent)->eeh_config_addr;
L
Linus Torvalds 已提交
931 932 933 934 935 936 937 938
				return NULL;
			}
		}
	} else {
		printk(KERN_WARNING "EEH: %s: unable to get reg property.\n",
		       dn->full_name);
	}

939
	eeh_save_bars(pdn);
L
Linas Vepstas 已提交
940
	return NULL;
L
Linus Torvalds 已提交
941 942
}

943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992
/**
 * eeh_ops_register - Register platform dependent EEH operations
 * @ops: platform dependent EEH operations
 *
 * Register the platform dependent EEH operation callback
 * functions. The platform should call this function before
 * any other EEH operations.
 */
int __init eeh_ops_register(struct eeh_ops *ops)
{
	if (!ops->name) {
		pr_warning("%s: Invalid EEH ops name for %p\n",
			__func__, ops);
		return -EINVAL;
	}

	if (eeh_ops && eeh_ops != ops) {
		pr_warning("%s: EEH ops of platform %s already existing (%s)\n",
			__func__, eeh_ops->name, ops->name);
		return -EEXIST;
	}

	eeh_ops = ops;

	return 0;
}

/**
 * eeh_ops_unregister - Unreigster platform dependent EEH operations
 * @name: name of EEH platform operations
 *
 * Unregister the platform dependent EEH operation callback
 * functions.
 */
int __exit eeh_ops_unregister(const char *name)
{
	if (!name || !strlen(name)) {
		pr_warning("%s: Invalid EEH ops name\n",
			__func__);
		return -EINVAL;
	}

	if (eeh_ops && !strcmp(eeh_ops->name, name)) {
		eeh_ops = NULL;
		return 0;
	}

	return -EEXIST;
}

993 994 995
/**
 * eeh_init - EEH initialization
 *
L
Linus Torvalds 已提交
996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010
 * Initialize EEH by trying to enable it for all of the adapters in the system.
 * As a side effect we can determine here if eeh is supported at all.
 * Note that we leave EEH on so failed config cycles won't cause a machine
 * check.  If a user turns off EEH for a particular adapter they are really
 * telling Linux to ignore errors.  Some hardware (e.g. POWER5) won't
 * grant access to a slot if EEH isn't enabled, and so we always enable
 * EEH for all slots/all devices.
 *
 * The eeh-force-off option disables EEH checking globally, for all slots.
 * Even if force-off is set, the EEH hardware is still enabled, so that
 * newer systems can boot.
 */
void __init eeh_init(void)
{
	struct device_node *phb, *np;
1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022
	int ret;

	/* call platform initialization function */
	if (!eeh_ops) {
		pr_warning("%s: Platform EEH operation not found\n",
			__func__);
		return;
	} else if ((ret = eeh_ops->init())) {
		pr_warning("%s: Failed to call platform init function (%d)\n",
			__func__, ret);
		return;
	}
L
Linus Torvalds 已提交
1023

1024
	raw_spin_lock_init(&confirm_error_lock);
1025

L
Linus Torvalds 已提交
1026 1027 1028 1029
	np = of_find_node_by_path("/rtas");
	if (np == NULL)
		return;

1030
	ibm_configure_bridge = rtas_token("ibm,configure-bridge");
1031
	ibm_configure_pe = rtas_token("ibm,configure-pe");
L
Linus Torvalds 已提交
1032 1033 1034 1035 1036 1037 1038

	/* Enable EEH for all adapters.  Note that eeh requires buid's */
	for (phb = of_find_node_by_name(NULL, "pci"); phb;
	     phb = of_find_node_by_name(phb, "pci")) {
		unsigned long buid;

		buid = get_phb_buid(phb);
L
Linas Vepstas 已提交
1039
		if (buid == 0 || PCI_DN(phb) == NULL)
L
Linus Torvalds 已提交
1040 1041
			continue;

1042
		traverse_pci_devices(phb, eeh_early_enable, NULL);
L
Linus Torvalds 已提交
1043 1044 1045 1046 1047 1048 1049 1050 1051
	}

	if (eeh_subsystem_enabled)
		printk(KERN_INFO "EEH: PCI Enhanced I/O Error Handling Enabled\n");
	else
		printk(KERN_WARNING "EEH: No capable adapters found\n");
}

/**
1052
 * eeh_add_device_early - Enable EEH for the indicated device_node
L
Linus Torvalds 已提交
1053 1054 1055 1056 1057 1058 1059 1060 1061 1062
 * @dn: device node for which to set up EEH
 *
 * This routine must be used to perform EEH initialization for PCI
 * devices that were added after system boot (e.g. hotplug, dlpar).
 * This routine must be called before any i/o is performed to the
 * adapter (inluding any config-space i/o).
 * Whether this actually enables EEH or not for this device depends
 * on the CEC architecture, type of the device, on earlier boot
 * command-line arguments & etc.
 */
1063
static void eeh_add_device_early(struct device_node *dn)
L
Linus Torvalds 已提交
1064 1065 1066
{
	struct pci_controller *phb;

L
Linas Vepstas 已提交
1067
	if (!dn || !PCI_DN(dn))
L
Linus Torvalds 已提交
1068
		return;
1069
	phb = PCI_DN(dn)->phb;
1070 1071 1072

	/* USB Bus children of PCI devices will not have BUID's */
	if (NULL == phb || 0 == phb->buid)
L
Linus Torvalds 已提交
1073 1074
		return;

1075
	eeh_early_enable(dn, NULL);
L
Linus Torvalds 已提交
1076 1077
}

1078 1079 1080 1081 1082 1083 1084 1085
/**
 * eeh_add_device_tree_early - Enable EEH for the indicated device
 * @dn: device node
 *
 * This routine must be used to perform EEH initialization for the
 * indicated PCI device that was added after system boot (e.g.
 * hotplug, dlpar).
 */
1086 1087 1088
void eeh_add_device_tree_early(struct device_node *dn)
{
	struct device_node *sib;
1089 1090

	for_each_child_of_node(dn, sib)
1091 1092 1093 1094 1095
		eeh_add_device_tree_early(sib);
	eeh_add_device_early(dn);
}
EXPORT_SYMBOL_GPL(eeh_add_device_tree_early);

L
Linus Torvalds 已提交
1096
/**
1097
 * eeh_add_device_late - Perform EEH initialization for the indicated pci device
L
Linus Torvalds 已提交
1098 1099 1100 1101 1102
 * @dev: pci device for which to set up EEH
 *
 * This routine must be used to complete EEH initialization for PCI
 * devices that were added after system boot (e.g. hotplug, dlpar).
 */
1103
static void eeh_add_device_late(struct pci_dev *dev)
L
Linus Torvalds 已提交
1104
{
1105
	struct device_node *dn;
1106
	struct pci_dn *pdn;
1107

L
Linus Torvalds 已提交
1108 1109 1110
	if (!dev || !eeh_subsystem_enabled)
		return;

1111
	pr_debug("EEH: Adding device %s\n", pci_name(dev));
L
Linus Torvalds 已提交
1112

1113
	dn = pci_device_to_OF_node(dev);
1114
	pdn = PCI_DN(dn);
1115 1116 1117 1118 1119 1120
	if (pdn->pcidev == dev) {
		pr_debug("EEH: Already referenced !\n");
		return;
	}
	WARN_ON(pdn->pcidev);

1121
	pci_dev_get(dev);
1122
	pdn->pcidev = dev;
1123

1124 1125
	pci_addr_cache_insert_device(dev);
	eeh_sysfs_add_device(dev);
L
Linus Torvalds 已提交
1126
}
1127

1128 1129 1130 1131 1132 1133 1134 1135
/**
 * eeh_add_device_tree_late - Perform EEH initialization for the indicated PCI bus
 * @bus: PCI bus
 *
 * This routine must be used to perform EEH initialization for PCI
 * devices which are attached to the indicated PCI bus. The PCI bus
 * is added after system boot through hotplug or dlpar.
 */
1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149
void eeh_add_device_tree_late(struct pci_bus *bus)
{
	struct pci_dev *dev;

	list_for_each_entry(dev, &bus->devices, bus_list) {
 		eeh_add_device_late(dev);
 		if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
 			struct pci_bus *subbus = dev->subordinate;
 			if (subbus)
 				eeh_add_device_tree_late(subbus);
 		}
	}
}
EXPORT_SYMBOL_GPL(eeh_add_device_tree_late);
L
Linus Torvalds 已提交
1150 1151

/**
1152
 * eeh_remove_device - Undo EEH setup for the indicated pci device
L
Linus Torvalds 已提交
1153 1154
 * @dev: pci device to be removed
 *
1155 1156 1157 1158 1159
 * This routine should be called when a device is removed from
 * a running system (e.g. by hotplug or dlpar).  It unregisters
 * the PCI device from the EEH subsystem.  I/O errors affecting
 * this device will no longer be detected after this call; thus,
 * i/o errors affecting this slot may leave this device unusable.
L
Linus Torvalds 已提交
1160
 */
1161
static void eeh_remove_device(struct pci_dev *dev)
L
Linus Torvalds 已提交
1162
{
1163
	struct device_node *dn;
L
Linus Torvalds 已提交
1164 1165 1166 1167
	if (!dev || !eeh_subsystem_enabled)
		return;

	/* Unregister the device with the EEH/PCI address search system */
1168
	pr_debug("EEH: Removing device %s\n", pci_name(dev));
1169 1170

	dn = pci_device_to_OF_node(dev);
1171 1172 1173
	if (PCI_DN(dn)->pcidev == NULL) {
		pr_debug("EEH: Not referenced !\n");
		return;
1174
	}
1175
	PCI_DN(dn)->pcidev = NULL;
1176
	pci_dev_put(dev);
1177 1178 1179

	pci_addr_cache_remove_device(dev);
	eeh_sysfs_remove_device(dev);
L
Linus Torvalds 已提交
1180 1181
}

1182 1183 1184 1185 1186 1187 1188 1189
/**
 * eeh_remove_bus_device - Undo EEH setup for the indicated PCI device
 * @dev: PCI device
 *
 * This routine must be called when a device is removed from the
 * running system through hotplug or dlpar. The corresponding
 * PCI address cache will be removed.
 */
1190 1191
void eeh_remove_bus_device(struct pci_dev *dev)
{
1192 1193 1194
	struct pci_bus *bus = dev->subordinate;
	struct pci_dev *child, *tmp;

1195
	eeh_remove_device(dev);
1196 1197 1198 1199

	if (bus && dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
		list_for_each_entry_safe(child, tmp, &bus->devices, bus_list)
			 eeh_remove_bus_device(child);
1200 1201 1202 1203
	}
}
EXPORT_SYMBOL_GPL(eeh_remove_bus_device);

L
Linus Torvalds 已提交
1204 1205 1206 1207
static int proc_eeh_show(struct seq_file *m, void *v)
{
	if (0 == eeh_subsystem_enabled) {
		seq_printf(m, "EEH Subsystem is globally disabled\n");
1208
		seq_printf(m, "eeh_total_mmio_ffs=%ld\n", total_mmio_ffs);
L
Linus Torvalds 已提交
1209 1210
	} else {
		seq_printf(m, "EEH Subsystem is enabled\n");
1211 1212 1213 1214 1215 1216 1217 1218
		seq_printf(m,
				"no device=%ld\n"
				"no device node=%ld\n"
				"no config address=%ld\n"
				"check not wanted=%ld\n"
				"eeh_total_mmio_ffs=%ld\n"
				"eeh_false_positives=%ld\n"
				"eeh_slot_resets=%ld\n",
1219 1220
				no_device, no_dn, no_cfg_addr, 
				ignored_check, total_mmio_ffs, 
L
Linas Vepstas 已提交
1221
				false_positives,
1222
				slot_resets);
L
Linus Torvalds 已提交
1223 1224 1225 1226 1227 1228 1229 1230 1231 1232
	}

	return 0;
}

static int proc_eeh_open(struct inode *inode, struct file *file)
{
	return single_open(file, proc_eeh_show, NULL);
}

1233
static const struct file_operations proc_eeh_operations = {
L
Linus Torvalds 已提交
1234 1235 1236 1237 1238 1239 1240 1241
	.open      = proc_eeh_open,
	.read      = seq_read,
	.llseek    = seq_lseek,
	.release   = single_release,
};

static int __init eeh_init_proc(void)
{
1242
	if (machine_is(pseries))
1243
		proc_create("powerpc/eeh", 0, NULL, &proc_eeh_operations);
L
Linus Torvalds 已提交
1244 1245 1246
	return 0;
}
__initcall(eeh_init_proc);