···11/*22- * eeh.h32 * Copyright (C) 2001 Dave Engebretsen & Todd Inglett IBM Corporation.33+ * Copyright 2001-2012 IBM Corporation.44 *55 * This program is free software; you can redistribute it and/or modify66 * it under the terms of the GNU General Public License as published by···31313232#ifdef CONFIG_EEH33333434+/*3535+ * The struct is used to trace EEH state for the associated3636+ * PCI device node or PCI device. In future, it might3737+ * represent PE as well so that the EEH device to form3838+ * another tree except the currently existing tree of PCI3939+ * buses and PCI devices4040+ */4141+#define EEH_MODE_SUPPORTED (1<<0) /* EEH supported on the device */4242+#define EEH_MODE_NOCHECK (1<<1) /* EEH check should be skipped */4343+#define EEH_MODE_ISOLATED (1<<2) /* The device has been isolated */4444+#define EEH_MODE_RECOVERING (1<<3) /* Recovering the device */4545+#define EEH_MODE_IRQ_DISABLED (1<<4) /* Interrupt disabled */4646+4747+struct eeh_dev {4848+ int mode; /* EEH mode */4949+ int class_code; /* Class code of the device */5050+ int config_addr; /* Config address */5151+ int pe_config_addr; /* PE config address */5252+ int check_count; /* Times of ignored error */5353+ int freeze_count; /* Times of froze up */5454+ int false_positives; /* Times of reported #ff's */5555+ u32 config_space[16]; /* Saved PCI config space */5656+ struct pci_controller *phb; /* Associated PHB */5757+ struct device_node *dn; /* Associated device node */5858+ struct pci_dev *pdev; /* Associated PCI device */5959+};6060+6161+static inline struct device_node *eeh_dev_to_of_node(struct eeh_dev *edev)6262+{6363+ return edev->dn;6464+}6565+6666+static inline struct pci_dev *eeh_dev_to_pci_dev(struct eeh_dev *edev)6767+{6868+ return edev->pdev;6969+}7070+7171+/*7272+ * The struct is used to trace the registered EEH operation7373+ * callback functions. Actually, those operation callback7474+ * functions are heavily platform dependent. That means the7575+ * platform should register its own EEH operation callback7676+ * functions before any EEH further operations.7777+ */7878+#define EEH_OPT_DISABLE 0 /* EEH disable */7979+#define EEH_OPT_ENABLE 1 /* EEH enable */8080+#define EEH_OPT_THAW_MMIO 2 /* MMIO enable */8181+#define EEH_OPT_THAW_DMA 3 /* DMA enable */8282+#define EEH_STATE_UNAVAILABLE (1 << 0) /* State unavailable */8383+#define EEH_STATE_NOT_SUPPORT (1 << 1) /* EEH not supported */8484+#define EEH_STATE_RESET_ACTIVE (1 << 2) /* Active reset */8585+#define EEH_STATE_MMIO_ACTIVE (1 << 3) /* Active MMIO */8686+#define EEH_STATE_DMA_ACTIVE (1 << 4) /* Active DMA */8787+#define EEH_STATE_MMIO_ENABLED (1 << 5) /* MMIO enabled */8888+#define EEH_STATE_DMA_ENABLED (1 << 6) /* DMA enabled */8989+#define EEH_RESET_DEACTIVATE 0 /* Deactivate the PE reset */9090+#define EEH_RESET_HOT 1 /* Hot reset */9191+#define EEH_RESET_FUNDAMENTAL 3 /* Fundamental reset */9292+#define EEH_LOG_TEMP 1 /* EEH temporary error log */9393+#define EEH_LOG_PERM 2 /* EEH permanent error log */9494+9595+struct eeh_ops {9696+ char *name;9797+ int (*init)(void);9898+ int (*set_option)(struct device_node *dn, int option);9999+ int (*get_pe_addr)(struct device_node *dn);100100+ int (*get_state)(struct device_node *dn, int *state);101101+ int (*reset)(struct device_node *dn, int option);102102+ int (*wait_state)(struct device_node *dn, int max_wait);103103+ int (*get_log)(struct device_node *dn, int severity, char *drv_log, unsigned long len);104104+ int (*configure_bridge)(struct device_node *dn);105105+ int (*read_config)(struct device_node *dn, int where, int size, u32 *val);106106+ int (*write_config)(struct device_node *dn, int where, int size, u32 val);107107+};108108+109109+extern struct eeh_ops *eeh_ops;34110extern int eeh_subsystem_enabled;351113636-/* Values for eeh_mode bits in device_node */3737-#define EEH_MODE_SUPPORTED (1<<0)3838-#define EEH_MODE_NOCHECK (1<<1)3939-#define EEH_MODE_ISOLATED (1<<2)4040-#define EEH_MODE_RECOVERING (1<<3)4141-#define EEH_MODE_IRQ_DISABLED (1<<4)4242-4343-/* Max number of EEH freezes allowed before we consider the device4444- * to be permanently disabled. */112112+/*113113+ * Max number of EEH freezes allowed before we consider the device114114+ * to be permanently disabled.115115+ */45116#define EEH_MAX_ALLOWED_FREEZES 546117118118+void * __devinit eeh_dev_init(struct device_node *dn, void *data);119119+void __devinit eeh_dev_phb_init_dynamic(struct pci_controller *phb);120120+void __init eeh_dev_phb_init(void);47121void __init eeh_init(void);122122+#ifdef CONFIG_PPC_PSERIES123123+int __init eeh_pseries_init(void);124124+#endif125125+int __init eeh_ops_register(struct eeh_ops *ops);126126+int __exit eeh_ops_unregister(const char *name);48127unsigned long eeh_check_failure(const volatile void __iomem *token,49128 unsigned long val);50129int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev);51130void __init pci_addr_cache_build(void);5252-5353-/**5454- * eeh_add_device_early5555- * eeh_add_device_late5656- *5757- * Perform eeh initialization for devices added after boot.5858- * Call eeh_add_device_early before doing any i/o to the5959- * device (including config space i/o). Call eeh_add_device_late6060- * to finish the eeh setup for this device.6161- */62131void eeh_add_device_tree_early(struct device_node *);63132void eeh_add_device_tree_late(struct pci_bus *);6464-6565-/**6666- * eeh_remove_device_recursive - undo EEH for device & children.6767- * @dev: pci device to be removed6868- *6969- * As above, this removes the device; it also removes child7070- * pci devices as well.7171- */72133void eeh_remove_bus_device(struct pci_dev *);7313474135/**···14887#define EEH_IO_ERROR_VALUE(size) (~0U >> ((4 - (size)) * 8))1498815089#else /* !CONFIG_EEH */9090+9191+static inline void *eeh_dev_init(struct device_node *dn, void *data)9292+{9393+ return NULL;9494+}9595+9696+static inline void eeh_dev_phb_init_dynamic(struct pci_controller *phb) { }9797+9898+static inline void eeh_dev_phb_init(void) { }9999+151100static inline void eeh_init(void) { }101101+102102+#ifdef CONFIG_PPC_PSERIES103103+static inline int eeh_pseries_init(void)104104+{105105+ return 0;106106+}107107+#endif /* CONFIG_PPC_PSERIES */152108153109static inline unsigned long eeh_check_failure(const volatile void __iomem *token, unsigned long val)154110{
+9-24
arch/powerpc/include/asm/eeh_event.h
···11/*22- * eeh_event.h33- *42 * This program is free software; you can redistribute it and/or modify53 * it under the terms of the GNU General Public License as published by64 * the Free Software Foundation; either version 2 of the License, or···2022#define ASM_POWERPC_EEH_EVENT_H2123#ifdef __KERNEL__22242323-/** EEH event -- structure holding pci controller data that describes2424- * a change in the isolation status of a PCI slot. A pointer2525- * to this struct is passed as the data pointer in a notify callback.2525+/*2626+ * structure holding pci controller data that describes a2727+ * change in the isolation status of a PCI slot. A pointer2828+ * to this struct is passed as the data pointer in a notify2929+ * callback.2630 */2731struct eeh_event {2828- struct list_head list;2929- struct device_node *dn; /* struct device node */3030- struct pci_dev *dev; /* affected device */3232+ struct list_head list; /* to form event queue */3333+ struct eeh_dev *edev; /* EEH device */3134};32353333-/**3434- * eeh_send_failure_event - generate a PCI error event3535- * @dev pci device3636- *3737- * This routine builds a PCI error event which will be delivered3838- * to all listeners on the eeh_notifier_chain.3939- *4040- * This routine can be called within an interrupt context;4141- * the actual event will be delivered in a normal context4242- * (from a workqueue).4343- */4444-int eeh_send_failure_event (struct device_node *dn,4545- struct pci_dev *dev);4646-4747-/* Main recovery function */4848-struct pci_dn * handle_eeh_events (struct eeh_event *);3636+int eeh_send_failure_event(struct eeh_dev *edev);3737+struct eeh_dev *handle_eeh_events(struct eeh_event *);49385039#endif /* __KERNEL__ */5140#endif /* ASM_POWERPC_EEH_EVENT_H */
+9-80
arch/powerpc/include/asm/ppc-pci.h
···47474848extern unsigned long pci_probe_only;49495050-/* ---- EEH internal-use-only related routines ---- */5150#ifdef CONFIG_EEH52515252+void pci_addr_cache_build(void);5353void pci_addr_cache_insert_device(struct pci_dev *dev);5454void pci_addr_cache_remove_device(struct pci_dev *dev);5555-void pci_addr_cache_build(void);5656-struct pci_dev *pci_get_device_by_addr(unsigned long addr);5757-5858-/**5959- * eeh_slot_error_detail -- record and EEH error condition to the log6060- * @pdn: pci device node6161- * @severity: EEH_LOG_TEMP_FAILURE or EEH_LOG_PERM_FAILURE6262- *6363- * Obtains the EEH error details from the RTAS subsystem,6464- * and then logs these details with the RTAS error log system.6565- */6666-#define EEH_LOG_TEMP_FAILURE 16767-#define EEH_LOG_PERM_FAILURE 26868-void eeh_slot_error_detail (struct pci_dn *pdn, int severity);6969-7070-/**7171- * rtas_pci_enable - enable IO transfers for this slot7272- * @pdn: pci device node7373- * @function: either EEH_THAW_MMIO or EEH_THAW_DMA 7474- *7575- * Enable I/O transfers to this slot 7676- */7777-#define EEH_THAW_MMIO 27878-#define EEH_THAW_DMA 37979-int rtas_pci_enable(struct pci_dn *pdn, int function);8080-8181-/**8282- * rtas_set_slot_reset -- unfreeze a frozen slot8383- * @pdn: pci device node8484- *8585- * Clear the EEH-frozen condition on a slot. This routine8686- * does this by asserting the PCI #RST line for 1/8th of8787- * a second; this routine will sleep while the adapter is8888- * being reset.8989- *9090- * Returns a non-zero value if the reset failed.9191- */9292-int rtas_set_slot_reset (struct pci_dn *);9393-int eeh_wait_for_slot_status(struct pci_dn *pdn, int max_wait_msecs);9494-9595-/** 9696- * eeh_restore_bars - Restore device configuration info.9797- * @pdn: pci device node9898- *9999- * A reset of a PCI device will clear out its config space.100100- * This routines will restore the config space for this101101- * device, and is children, to values previously obtained102102- * from the firmware.103103- */104104-void eeh_restore_bars(struct pci_dn *);105105-106106-/**107107- * rtas_configure_bridge -- firmware initialization of pci bridge108108- * @pdn: pci device node109109- *110110- * Ask the firmware to configure all PCI bridges devices111111- * located behind the indicated node. Required after a112112- * pci device reset. Does essentially the same hing as113113- * eeh_restore_bars, but for brdges, and lets firmware 114114- * do the work.115115- */116116-void rtas_configure_bridge(struct pci_dn *);117117-5555+struct pci_dev *pci_addr_cache_get_device(unsigned long addr);5656+void eeh_slot_error_detail(struct eeh_dev *edev, int severity);5757+int eeh_pci_enable(struct eeh_dev *edev, int function);5858+int eeh_reset_pe(struct eeh_dev *);5959+void eeh_restore_bars(struct eeh_dev *);11860int rtas_write_config(struct pci_dn *, int where, int size, u32 val);11961int rtas_read_config(struct pci_dn *, int where, int size, u32 *val);120120-121121-/**122122- * eeh_mark_slot -- set mode flags for pertition endpoint123123- * @pdn: pci device node124124- *125125- * mark and clear slots: find "partition endpoint" PE and set or 126126- * clear the flags for each subnode of the PE.127127- */128128-void eeh_mark_slot (struct device_node *dn, int mode_flag);129129-void eeh_clear_slot (struct device_node *dn, int mode_flag);130130-131131-/**132132- * find_device_pe -- Find the associated "Partiationable Endpoint" PE133133- * @pdn: pci device node134134- */135135-struct device_node * find_device_pe(struct device_node *dn);6262+void eeh_mark_slot(struct device_node *dn, int mode_flag);6363+void eeh_clear_slot(struct device_node *dn, int mode_flag);6464+struct device_node *eeh_find_device_pe(struct device_node *dn);1366513766void eeh_sysfs_add_device(struct pci_dev *pdev);13867void eeh_sysfs_remove_device(struct pci_dev *pdev);
+5-1
arch/powerpc/kernel/of_platform.c
···2121#include <linux/of.h>2222#include <linux/of_device.h>2323#include <linux/of_platform.h>2424+#include <linux/atomic.h>24252526#include <asm/errno.h>2627#include <asm/topology.h>2728#include <asm/pci-bridge.h>2829#include <asm/ppc-pci.h>2929-#include <linux/atomic.h>3030+#include <asm/eeh.h>30313132#ifdef CONFIG_PPC_OF_PLATFORM_PCI3233···66656766 /* Init pci_dn data structures */6867 pci_devs_phb_init_dynamic(phb);6868+6969+ /* Create EEH devices for the PHB */7070+ eeh_dev_phb_init_dynamic(phb);69717072 /* Register devices with EEH */7173#ifdef CONFIG_EEH
+3
arch/powerpc/kernel/rtas_pci.c
···275275 of_node_put(root);276276 pci_devs_phb_init();277277278278+ /* Create EEH devices for all PHBs */279279+ eeh_dev_phb_init();280280+278281 /*279282 * pci_probe_only and pci_assign_all_buses can be set via properties280283 * in chosen.
···11/*22- * eeh.c32 * Copyright IBM Corporation 2001, 2005, 200643 * Copyright Dave Engebretsen & Todd Inglett 200154 * Copyright Linas Vepstas 2005, 200655+ * Copyright 2001-2012 IBM Corporation.66 *77 * This program is free software; you can redistribute it and/or modify88 * it under the terms of the GNU General Public License as published by···2222 */23232424#include <linux/delay.h>2525-#include <linux/sched.h> /* for init_mm */2525+#include <linux/sched.h>2626#include <linux/init.h>2727#include <linux/list.h>2828#include <linux/pci.h>···8686/* Time to wait for a PCI slot to report status, in milliseconds */8787#define PCI_BUS_RESET_WAIT_MSEC (60*1000)88888989-/* RTAS tokens */9090-static int ibm_set_eeh_option;9191-static int ibm_set_slot_reset;9292-static int ibm_read_slot_reset_state;9393-static int ibm_read_slot_reset_state2;9494-static int ibm_slot_error_detail;9595-static int ibm_get_config_addr_info;9696-static int ibm_get_config_addr_info2;9797-static int ibm_configure_bridge;9898-static int ibm_configure_pe;8989+/* Platform dependent EEH operations */9090+struct eeh_ops *eeh_ops = NULL;999110092int eeh_subsystem_enabled;10193EXPORT_SYMBOL(eeh_subsystem_enabled);1029410395/* Lock to avoid races due to multiple reports of an error */10496static DEFINE_RAW_SPINLOCK(confirm_error_lock);105105-106106-/* Buffer for reporting slot-error-detail rtas calls. Its here107107- * in BSS, and not dynamically alloced, so that it ends up in108108- * RMO where RTAS can access it.109109- */110110-static unsigned char slot_errbuf[RTAS_ERROR_LOG_MAX];111111-static DEFINE_SPINLOCK(slot_errbuf_lock);112112-static int eeh_error_buf_size;1139711498/* Buffer for reporting pci register dumps. Its here in BSS, and11599 * not dynamically alloced, so that it ends up in RMO where RTAS···102118#define EEH_PCI_REGS_LOG_LEN 4096103119static unsigned char pci_regs_buf[EEH_PCI_REGS_LOG_LEN];104120105105-/* System monitoring statistics */106106-static unsigned long no_device;107107-static unsigned long no_dn;108108-static unsigned long no_cfg_addr;109109-static unsigned long ignored_check;110110-static unsigned long total_mmio_ffs;111111-static unsigned long false_positives;112112-static unsigned long slot_resets;121121+/*122122+ * The struct is used to maintain the EEH global statistic123123+ * information. Besides, the EEH global statistics will be124124+ * exported to user space through procfs125125+ */126126+struct eeh_stats {127127+ u64 no_device; /* PCI device not found */128128+ u64 no_dn; /* OF node not found */129129+ u64 no_cfg_addr; /* Config address not found */130130+ u64 ignored_check; /* EEH check skipped */131131+ u64 total_mmio_ffs; /* Total EEH checks */132132+ u64 false_positives; /* Unnecessary EEH checks */133133+ u64 slot_resets; /* PE reset */134134+};135135+136136+static struct eeh_stats eeh_stats;113137114138#define IS_BRIDGE(class_code) (((class_code)<<16) == PCI_BASE_CLASS_BRIDGE)115139116116-/* --------------------------------------------------------------- */117117-/* Below lies the EEH event infrastructure */118118-119119-static void rtas_slot_error_detail(struct pci_dn *pdn, int severity,120120- char *driver_log, size_t loglen)121121-{122122- int config_addr;123123- unsigned long flags;124124- int rc;125125-126126- /* Log the error with the rtas logger */127127- spin_lock_irqsave(&slot_errbuf_lock, flags);128128- memset(slot_errbuf, 0, eeh_error_buf_size);129129-130130- /* Use PE configuration address, if present */131131- config_addr = pdn->eeh_config_addr;132132- if (pdn->eeh_pe_config_addr)133133- config_addr = pdn->eeh_pe_config_addr;134134-135135- rc = rtas_call(ibm_slot_error_detail,136136- 8, 1, NULL, config_addr,137137- BUID_HI(pdn->phb->buid),138138- BUID_LO(pdn->phb->buid),139139- virt_to_phys(driver_log), loglen,140140- virt_to_phys(slot_errbuf),141141- eeh_error_buf_size,142142- severity);143143-144144- if (rc == 0)145145- log_error(slot_errbuf, ERR_TYPE_RTAS_LOG, 0);146146- spin_unlock_irqrestore(&slot_errbuf_lock, flags);147147-}148148-149140/**150150- * gather_pci_data - copy assorted PCI config space registers to buff151151- * @pdn: device to report data for141141+ * eeh_gather_pci_data - Copy assorted PCI config space registers to buff142142+ * @edev: device to report data for152143 * @buf: point to buffer in which to log153144 * @len: amount of room in buffer154145 *155146 * This routine captures assorted PCI configuration space data,156147 * and puts them into a buffer for RTAS error logging.157148 */158158-static size_t gather_pci_data(struct pci_dn *pdn, char * buf, size_t len)149149+static size_t eeh_gather_pci_data(struct eeh_dev *edev, char * buf, size_t len)159150{160160- struct pci_dev *dev = pdn->pcidev;151151+ struct device_node *dn = eeh_dev_to_of_node(edev);152152+ struct pci_dev *dev = eeh_dev_to_pci_dev(edev);161153 u32 cfg;162154 int cap, i;163155 int n = 0;164156165165- n += scnprintf(buf+n, len-n, "%s\n", pdn->node->full_name);166166- printk(KERN_WARNING "EEH: of node=%s\n", pdn->node->full_name);157157+ n += scnprintf(buf+n, len-n, "%s\n", dn->full_name);158158+ printk(KERN_WARNING "EEH: of node=%s\n", dn->full_name);167159168168- rtas_read_config(pdn, PCI_VENDOR_ID, 4, &cfg);160160+ eeh_ops->read_config(dn, PCI_VENDOR_ID, 4, &cfg);169161 n += scnprintf(buf+n, len-n, "dev/vend:%08x\n", cfg);170162 printk(KERN_WARNING "EEH: PCI device/vendor: %08x\n", cfg);171163172172- rtas_read_config(pdn, PCI_COMMAND, 4, &cfg);164164+ eeh_ops->read_config(dn, PCI_COMMAND, 4, &cfg);173165 n += scnprintf(buf+n, len-n, "cmd/stat:%x\n", cfg);174166 printk(KERN_WARNING "EEH: PCI cmd/status register: %08x\n", cfg);175167···156196157197 /* Gather bridge-specific registers */158198 if (dev->class >> 16 == PCI_BASE_CLASS_BRIDGE) {159159- rtas_read_config(pdn, PCI_SEC_STATUS, 2, &cfg);199199+ eeh_ops->read_config(dn, PCI_SEC_STATUS, 2, &cfg);160200 n += scnprintf(buf+n, len-n, "sec stat:%x\n", cfg);161201 printk(KERN_WARNING "EEH: Bridge secondary status: %04x\n", cfg);162202163163- rtas_read_config(pdn, PCI_BRIDGE_CONTROL, 2, &cfg);203203+ eeh_ops->read_config(dn, PCI_BRIDGE_CONTROL, 2, &cfg);164204 n += scnprintf(buf+n, len-n, "brdg ctl:%x\n", cfg);165205 printk(KERN_WARNING "EEH: Bridge control: %04x\n", cfg);166206 }···168208 /* Dump out the PCI-X command and status regs */169209 cap = pci_find_capability(dev, PCI_CAP_ID_PCIX);170210 if (cap) {171171- rtas_read_config(pdn, cap, 4, &cfg);211211+ eeh_ops->read_config(dn, cap, 4, &cfg);172212 n += scnprintf(buf+n, len-n, "pcix-cmd:%x\n", cfg);173213 printk(KERN_WARNING "EEH: PCI-X cmd: %08x\n", cfg);174214175175- rtas_read_config(pdn, cap+4, 4, &cfg);215215+ eeh_ops->read_config(dn, cap+4, 4, &cfg);176216 n += scnprintf(buf+n, len-n, "pcix-stat:%x\n", cfg);177217 printk(KERN_WARNING "EEH: PCI-X status: %08x\n", cfg);178218 }···185225 "EEH: PCI-E capabilities and status follow:\n");186226187227 for (i=0; i<=8; i++) {188188- rtas_read_config(pdn, cap+4*i, 4, &cfg);228228+ eeh_ops->read_config(dn, cap+4*i, 4, &cfg);189229 n += scnprintf(buf+n, len-n, "%02x:%x\n", 4*i, cfg);190230 printk(KERN_WARNING "EEH: PCI-E %02x: %08x\n", i, cfg);191231 }···197237 "EEH: PCI-E AER capability register set follows:\n");198238199239 for (i=0; i<14; i++) {200200- rtas_read_config(pdn, cap+4*i, 4, &cfg);240240+ eeh_ops->read_config(dn, cap+4*i, 4, &cfg);201241 n += scnprintf(buf+n, len-n, "%02x:%x\n", 4*i, cfg);202242 printk(KERN_WARNING "EEH: PCI-E AER %02x: %08x\n", i, cfg);203243 }···206246207247 /* Gather status on devices under the bridge */208248 if (dev->class >> 16 == PCI_BASE_CLASS_BRIDGE) {209209- struct device_node *dn;249249+ struct device_node *child;210250211211- for_each_child_of_node(pdn->node, dn) {212212- pdn = PCI_DN(dn);213213- if (pdn)214214- n += gather_pci_data(pdn, buf+n, len-n);251251+ for_each_child_of_node(dn, child) {252252+ if (of_node_to_eeh_dev(child))253253+ n += eeh_gather_pci_data(of_node_to_eeh_dev(child), buf+n, len-n);215254 }216255 }217256218257 return n;219258}220259221221-void eeh_slot_error_detail(struct pci_dn *pdn, int severity)260260+/**261261+ * eeh_slot_error_detail - Generate combined log including driver log and error log262262+ * @edev: device to report error log for263263+ * @severity: temporary or permanent error log264264+ *265265+ * This routine should be called to generate the combined log, which266266+ * is comprised of driver log and error log. The driver log is figured267267+ * out from the config space of the corresponding PCI device, while268268+ * the error log is fetched through platform dependent function call.269269+ */270270+void eeh_slot_error_detail(struct eeh_dev *edev, int severity)222271{223272 size_t loglen = 0;224273 pci_regs_buf[0] = 0;225274226226- rtas_pci_enable(pdn, EEH_THAW_MMIO);227227- rtas_configure_bridge(pdn);228228- eeh_restore_bars(pdn);229229- loglen = gather_pci_data(pdn, pci_regs_buf, EEH_PCI_REGS_LOG_LEN);275275+ eeh_pci_enable(edev, EEH_OPT_THAW_MMIO);276276+ eeh_ops->configure_bridge(eeh_dev_to_of_node(edev));277277+ eeh_restore_bars(edev);278278+ loglen = eeh_gather_pci_data(edev, pci_regs_buf, EEH_PCI_REGS_LOG_LEN);230279231231- rtas_slot_error_detail(pdn, severity, pci_regs_buf, loglen);280280+ eeh_ops->get_log(eeh_dev_to_of_node(edev), severity, pci_regs_buf, loglen);232281}233282234283/**235235- * read_slot_reset_state - Read the reset state of a device node's slot236236- * @dn: device node to read237237- * @rets: array to return results in238238- */239239-static int read_slot_reset_state(struct pci_dn *pdn, int rets[])240240-{241241- int token, outputs;242242- int config_addr;243243-244244- if (ibm_read_slot_reset_state2 != RTAS_UNKNOWN_SERVICE) {245245- token = ibm_read_slot_reset_state2;246246- outputs = 4;247247- } else {248248- token = ibm_read_slot_reset_state;249249- rets[2] = 0; /* fake PE Unavailable info */250250- outputs = 3;251251- }252252-253253- /* Use PE configuration address, if present */254254- config_addr = pdn->eeh_config_addr;255255- if (pdn->eeh_pe_config_addr)256256- config_addr = pdn->eeh_pe_config_addr;257257-258258- return rtas_call(token, 3, outputs, rets, config_addr,259259- BUID_HI(pdn->phb->buid), BUID_LO(pdn->phb->buid));260260-}261261-262262-/**263263- * eeh_wait_for_slot_status - returns error status of slot264264- * @pdn pci device node265265- * @max_wait_msecs maximum number to millisecs to wait284284+ * eeh_token_to_phys - Convert EEH address token to phys address285285+ * @token: I/O token, should be address in the form 0xA....266286 *267267- * Return negative value if a permanent error, else return268268- * Partition Endpoint (PE) status value.269269- *270270- * If @max_wait_msecs is positive, then this routine will271271- * sleep until a valid status can be obtained, or until272272- * the max allowed wait time is exceeded, in which case273273- * a -2 is returned.274274- */275275-int276276-eeh_wait_for_slot_status(struct pci_dn *pdn, int max_wait_msecs)277277-{278278- int rc;279279- int rets[3];280280- int mwait;281281-282282- while (1) {283283- rc = read_slot_reset_state(pdn, rets);284284- if (rc) return rc;285285- if (rets[1] == 0) return -1; /* EEH is not supported */286286-287287- if (rets[0] != 5) return rets[0]; /* return actual status */288288-289289- if (rets[2] == 0) return -1; /* permanently unavailable */290290-291291- if (max_wait_msecs <= 0) break;292292-293293- mwait = rets[2];294294- if (mwait <= 0) {295295- printk (KERN_WARNING296296- "EEH: Firmware returned bad wait value=%d\n", mwait);297297- mwait = 1000;298298- } else if (mwait > 300*1000) {299299- printk (KERN_WARNING300300- "EEH: Firmware is taking too long, time=%d\n", mwait);301301- mwait = 300*1000;302302- }303303- max_wait_msecs -= mwait;304304- msleep (mwait);305305- }306306-307307- printk(KERN_WARNING "EEH: Timed out waiting for slot status\n");308308- return -2;309309-}310310-311311-/**312312- * eeh_token_to_phys - convert EEH address token to phys address313313- * @token i/o token, should be address in the form 0xA....287287+ * This routine should be called to convert virtual I/O address288288+ * to physical one.314289 */315290static inline unsigned long eeh_token_to_phys(unsigned long token)316291{···260365 return pa | (token & (PAGE_SIZE-1));261366}262367263263-/** 264264- * Return the "partitionable endpoint" (pe) under which this device lies368368+/**369369+ * eeh_find_device_pe - Retrieve the PE for the given device370370+ * @dn: device node371371+ *372372+ * Return the PE under which this device lies265373 */266266-struct device_node * find_device_pe(struct device_node *dn)374374+struct device_node *eeh_find_device_pe(struct device_node *dn)267375{268268- while ((dn->parent) && PCI_DN(dn->parent) &&269269- (PCI_DN(dn->parent)->eeh_mode & EEH_MODE_SUPPORTED)) {376376+ while (dn->parent && of_node_to_eeh_dev(dn->parent) &&377377+ (of_node_to_eeh_dev(dn->parent)->mode & EEH_MODE_SUPPORTED)) {270378 dn = dn->parent;271379 }272380 return dn;273381}274382275275-/** Mark all devices that are children of this device as failed.276276- * Mark the device driver too, so that it can see the failure277277- * immediately; this is critical, since some drivers poll278278- * status registers in interrupts ... If a driver is polling,279279- * and the slot is frozen, then the driver can deadlock in280280- * an interrupt context, which is bad.383383+/**384384+ * __eeh_mark_slot - Mark all child devices as failed385385+ * @parent: parent device386386+ * @mode_flag: failure flag387387+ *388388+ * Mark all devices that are children of this device as failed.389389+ * Mark the device driver too, so that it can see the failure390390+ * immediately; this is critical, since some drivers poll391391+ * status registers in interrupts ... If a driver is polling,392392+ * and the slot is frozen, then the driver can deadlock in393393+ * an interrupt context, which is bad.281394 */282282-283395static void __eeh_mark_slot(struct device_node *parent, int mode_flag)284396{285397 struct device_node *dn;286398287399 for_each_child_of_node(parent, dn) {288288- if (PCI_DN(dn)) {400400+ if (of_node_to_eeh_dev(dn)) {289401 /* Mark the pci device driver too */290290- struct pci_dev *dev = PCI_DN(dn)->pcidev;402402+ struct pci_dev *dev = of_node_to_eeh_dev(dn)->pdev;291403292292- PCI_DN(dn)->eeh_mode |= mode_flag;404404+ of_node_to_eeh_dev(dn)->mode |= mode_flag;293405294406 if (dev && dev->driver)295407 dev->error_state = pci_channel_io_frozen;···306404 }307405}308406309309-void eeh_mark_slot (struct device_node *dn, int mode_flag)407407+/**408408+ * eeh_mark_slot - Mark the indicated device and its children as failed409409+ * @dn: parent device410410+ * @mode_flag: failure flag411411+ *412412+ * Mark the indicated device and its child devices as failed.413413+ * The device drivers are marked as failed as well.414414+ */415415+void eeh_mark_slot(struct device_node *dn, int mode_flag)310416{311417 struct pci_dev *dev;312312- dn = find_device_pe (dn);418418+ dn = eeh_find_device_pe(dn);313419314420 /* Back up one, since config addrs might be shared */315315- if (!pcibios_find_pci_bus(dn) && PCI_DN(dn->parent))421421+ if (!pcibios_find_pci_bus(dn) && of_node_to_eeh_dev(dn->parent))316422 dn = dn->parent;317423318318- PCI_DN(dn)->eeh_mode |= mode_flag;424424+ of_node_to_eeh_dev(dn)->mode |= mode_flag;319425320426 /* Mark the pci device too */321321- dev = PCI_DN(dn)->pcidev;427427+ dev = of_node_to_eeh_dev(dn)->pdev;322428 if (dev)323429 dev->error_state = pci_channel_io_frozen;324430325431 __eeh_mark_slot(dn, mode_flag);326432}327433434434+/**435435+ * __eeh_clear_slot - Clear failure flag for the child devices436436+ * @parent: parent device437437+ * @mode_flag: flag to be cleared438438+ *439439+ * Clear failure flag for the child devices.440440+ */328441static void __eeh_clear_slot(struct device_node *parent, int mode_flag)329442{330443 struct device_node *dn;331444332445 for_each_child_of_node(parent, dn) {333333- if (PCI_DN(dn)) {334334- PCI_DN(dn)->eeh_mode &= ~mode_flag;335335- PCI_DN(dn)->eeh_check_count = 0;446446+ if (of_node_to_eeh_dev(dn)) {447447+ of_node_to_eeh_dev(dn)->mode &= ~mode_flag;448448+ of_node_to_eeh_dev(dn)->check_count = 0;336449 __eeh_clear_slot(dn, mode_flag);337450 }338451 }339452}340453341341-void eeh_clear_slot (struct device_node *dn, int mode_flag)454454+/**455455+ * eeh_clear_slot - Clear failure flag for the indicated device and its children456456+ * @dn: parent device457457+ * @mode_flag: flag to be cleared458458+ *459459+ * Clear failure flag for the indicated device and its children.460460+ */461461+void eeh_clear_slot(struct device_node *dn, int mode_flag)342462{343463 unsigned long flags;344464 raw_spin_lock_irqsave(&confirm_error_lock, flags);345465346346- dn = find_device_pe (dn);466466+ dn = eeh_find_device_pe(dn);347467348468 /* Back up one, since config addrs might be shared */349349- if (!pcibios_find_pci_bus(dn) && PCI_DN(dn->parent))469469+ if (!pcibios_find_pci_bus(dn) && of_node_to_eeh_dev(dn->parent))350470 dn = dn->parent;351471352352- PCI_DN(dn)->eeh_mode &= ~mode_flag;353353- PCI_DN(dn)->eeh_check_count = 0;472472+ of_node_to_eeh_dev(dn)->mode &= ~mode_flag;473473+ of_node_to_eeh_dev(dn)->check_count = 0;354474 __eeh_clear_slot(dn, mode_flag);355475 raw_spin_unlock_irqrestore(&confirm_error_lock, flags);356476}357477358358-void __eeh_set_pe_freset(struct device_node *parent, unsigned int *freset)359359-{360360- struct device_node *dn;361361-362362- for_each_child_of_node(parent, dn) {363363- if (PCI_DN(dn)) {364364-365365- struct pci_dev *dev = PCI_DN(dn)->pcidev;366366-367367- if (dev && dev->driver)368368- *freset |= dev->needs_freset;369369-370370- __eeh_set_pe_freset(dn, freset);371371- }372372- }373373-}374374-375375-void eeh_set_pe_freset(struct device_node *dn, unsigned int *freset)376376-{377377- struct pci_dev *dev;378378- dn = find_device_pe(dn);379379-380380- /* Back up one, since config addrs might be shared */381381- if (!pcibios_find_pci_bus(dn) && PCI_DN(dn->parent))382382- dn = dn->parent;383383-384384- dev = PCI_DN(dn)->pcidev;385385- if (dev)386386- *freset |= dev->needs_freset;387387-388388- __eeh_set_pe_freset(dn, freset);389389-}390390-391478/**392392- * eeh_dn_check_failure - check if all 1's data is due to EEH slot freeze393393- * @dn device node394394- * @dev pci device, if known479479+ * eeh_dn_check_failure - Check if all 1's data is due to EEH slot freeze480480+ * @dn: device node481481+ * @dev: pci device, if known395482 *396483 * Check for an EEH failure for the given device node. Call this397484 * routine if the result of a read was all 0xff's and you want to···395504int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev)396505{397506 int ret;398398- int rets[3];399507 unsigned long flags;400400- struct pci_dn *pdn;508508+ struct eeh_dev *edev;401509 int rc = 0;402510 const char *location;403511404404- total_mmio_ffs++;512512+ eeh_stats.total_mmio_ffs++;405513406514 if (!eeh_subsystem_enabled)407515 return 0;408516409517 if (!dn) {410410- no_dn++;518518+ eeh_stats.no_dn++;411519 return 0;412520 }413413- dn = find_device_pe(dn);414414- pdn = PCI_DN(dn);521521+ dn = eeh_find_device_pe(dn);522522+ edev = of_node_to_eeh_dev(dn);415523416524 /* Access to IO BARs might get this far and still not want checking. */417417- if (!(pdn->eeh_mode & EEH_MODE_SUPPORTED) ||418418- pdn->eeh_mode & EEH_MODE_NOCHECK) {419419- ignored_check++;525525+ if (!(edev->mode & EEH_MODE_SUPPORTED) ||526526+ edev->mode & EEH_MODE_NOCHECK) {527527+ eeh_stats.ignored_check++;420528 pr_debug("EEH: Ignored check (%x) for %s %s\n",421421- pdn->eeh_mode, eeh_pci_name(dev), dn->full_name);529529+ edev->mode, eeh_pci_name(dev), dn->full_name);422530 return 0;423531 }424532425425- if (!pdn->eeh_config_addr && !pdn->eeh_pe_config_addr) {426426- no_cfg_addr++;533533+ if (!edev->config_addr && !edev->pe_config_addr) {534534+ eeh_stats.no_cfg_addr++;427535 return 0;428536 }429537···434544 */435545 raw_spin_lock_irqsave(&confirm_error_lock, flags);436546 rc = 1;437437- if (pdn->eeh_mode & EEH_MODE_ISOLATED) {438438- pdn->eeh_check_count ++;439439- if (pdn->eeh_check_count % EEH_MAX_FAILS == 0) {547547+ if (edev->mode & EEH_MODE_ISOLATED) {548548+ edev->check_count++;549549+ if (edev->check_count % EEH_MAX_FAILS == 0) {440550 location = of_get_property(dn, "ibm,loc-code", NULL);441441- printk (KERN_ERR "EEH: %d reads ignored for recovering device at "551551+ printk(KERN_ERR "EEH: %d reads ignored for recovering device at "442552 "location=%s driver=%s pci addr=%s\n",443443- pdn->eeh_check_count, location,553553+ edev->check_count, location,444554 eeh_driver_name(dev), eeh_pci_name(dev));445445- printk (KERN_ERR "EEH: Might be infinite loop in %s driver\n",555555+ printk(KERN_ERR "EEH: Might be infinite loop in %s driver\n",446556 eeh_driver_name(dev));447557 dump_stack();448558 }···456566 * function zero of a multi-function device.457567 * In any case they must share a common PHB.458568 */459459- ret = read_slot_reset_state(pdn, rets);460460-461461- /* If the call to firmware failed, punt */462462- if (ret != 0) {463463- printk(KERN_WARNING "EEH: read_slot_reset_state() failed; rc=%d dn=%s\n",464464- ret, dn->full_name);465465- false_positives++;466466- pdn->eeh_false_positives ++;467467- rc = 0;468468- goto dn_unlock;469469- }569569+ ret = eeh_ops->get_state(dn, NULL);470570471571 /* Note that config-io to empty slots may fail;472472- * they are empty when they don't have children. */473473- if ((rets[0] == 5) && (rets[2] == 0) && (dn->child == NULL)) {474474- false_positives++;475475- pdn->eeh_false_positives ++;572572+ * they are empty when they don't have children.573573+ * We will punt with the following conditions: Failure to get574574+ * PE's state, EEH not support and Permanently unavailable575575+ * state, PE is in good state.576576+ */577577+ if ((ret < 0) ||578578+ (ret == EEH_STATE_NOT_SUPPORT) ||579579+ (ret & (EEH_STATE_MMIO_ACTIVE | EEH_STATE_DMA_ACTIVE)) ==580580+ (EEH_STATE_MMIO_ACTIVE | EEH_STATE_DMA_ACTIVE)) {581581+ eeh_stats.false_positives++;582582+ edev->false_positives ++;476583 rc = 0;477584 goto dn_unlock;478585 }479586480480- /* If EEH is not supported on this device, punt. */481481- if (rets[1] != 1) {482482- printk(KERN_WARNING "EEH: event on unsupported device, rc=%d dn=%s\n",483483- ret, dn->full_name);484484- false_positives++;485485- pdn->eeh_false_positives ++;486486- rc = 0;487487- goto dn_unlock;488488- }489489-490490- /* If not the kind of error we know about, punt. */491491- if (rets[0] != 1 && rets[0] != 2 && rets[0] != 4 && rets[0] != 5) {492492- false_positives++;493493- pdn->eeh_false_positives ++;494494- rc = 0;495495- goto dn_unlock;496496- }497497-498498- slot_resets++;587587+ eeh_stats.slot_resets++;499588500589 /* Avoid repeated reports of this failure, including problems501590 * with other functions on this device, and functions under502502- * bridges. */503503- eeh_mark_slot (dn, EEH_MODE_ISOLATED);591591+ * bridges.592592+ */593593+ eeh_mark_slot(dn, EEH_MODE_ISOLATED);504594 raw_spin_unlock_irqrestore(&confirm_error_lock, flags);505595506506- eeh_send_failure_event (dn, dev);596596+ eeh_send_failure_event(edev);507597508598 /* Most EEH events are due to device driver bugs. Having509599 * a stack trace will help the device-driver authors figure510510- * out what happened. So print that out. */600600+ * out what happened. So print that out.601601+ */511602 dump_stack();512603 return 1;513604···500629EXPORT_SYMBOL_GPL(eeh_dn_check_failure);501630502631/**503503- * eeh_check_failure - check if all 1's data is due to EEH slot freeze504504- * @token i/o token, should be address in the form 0xA....505505- * @val value, should be all 1's (XXX why do we need this arg??)632632+ * eeh_check_failure - Check if all 1's data is due to EEH slot freeze633633+ * @token: I/O token, should be address in the form 0xA....634634+ * @val: value, should be all 1's (XXX why do we need this arg??)506635 *507636 * Check for an EEH failure at the given token address. Call this508637 * routine if the result of a read was all 0xff's and you want to···519648520649 /* Finding the phys addr + pci device; this is pretty quick. */521650 addr = eeh_token_to_phys((unsigned long __force) token);522522- dev = pci_get_device_by_addr(addr);651651+ dev = pci_addr_cache_get_device(addr);523652 if (!dev) {524524- no_device++;653653+ eeh_stats.no_device++;525654 return val;526655 }527656528657 dn = pci_device_to_OF_node(dev);529529- eeh_dn_check_failure (dn, dev);658658+ eeh_dn_check_failure(dn, dev);530659531660 pci_dev_put(dev);532661 return val;···534663535664EXPORT_SYMBOL(eeh_check_failure);536665537537-/* ------------------------------------------------------------- */538538-/* The code below deals with error recovery */539666540667/**541541- * rtas_pci_enable - enable MMIO or DMA transfers for this slot542542- * @pdn pci device node668668+ * eeh_pci_enable - Enable MMIO or DMA transfers for this slot669669+ * @edev: pci device node670670+ *671671+ * This routine should be called to reenable frozen MMIO or DMA672672+ * so that it would work correctly again. It's useful while doing673673+ * recovery or log collection on the indicated device.543674 */544544-545545-int546546-rtas_pci_enable(struct pci_dn *pdn, int function)675675+int eeh_pci_enable(struct eeh_dev *edev, int function)547676{548548- int config_addr;549677 int rc;678678+ struct device_node *dn = eeh_dev_to_of_node(edev);550679551551- /* Use PE configuration address, if present */552552- config_addr = pdn->eeh_config_addr;553553- if (pdn->eeh_pe_config_addr)554554- config_addr = pdn->eeh_pe_config_addr;555555-556556- rc = rtas_call(ibm_set_eeh_option, 4, 1, NULL,557557- config_addr,558558- BUID_HI(pdn->phb->buid),559559- BUID_LO(pdn->phb->buid),560560- function);561561-680680+ rc = eeh_ops->set_option(dn, function);562681 if (rc)563682 printk(KERN_WARNING "EEH: Unexpected state change %d, err=%d dn=%s\n",564564- function, rc, pdn->node->full_name);683683+ function, rc, dn->full_name);565684566566- rc = eeh_wait_for_slot_status (pdn, PCI_BUS_RESET_WAIT_MSEC);567567- if ((rc == 4) && (function == EEH_THAW_MMIO))685685+ rc = eeh_ops->wait_state(dn, PCI_BUS_RESET_WAIT_MSEC);686686+ if (rc > 0 && (rc & EEH_STATE_MMIO_ENABLED) &&687687+ (function == EEH_OPT_THAW_MMIO))568688 return 0;569689570690 return rc;571691}572692573693/**574574- * rtas_pci_slot_reset - raises/lowers the pci #RST line575575- * @pdn pci device node576576- * @state: 1/0 to raise/lower the #RST577577- *578578- * Clear the EEH-frozen condition on a slot. This routine579579- * asserts the PCI #RST line if the 'state' argument is '1',580580- * and drops the #RST line if 'state is '0'. This routine is581581- * safe to call in an interrupt context.582582- *583583- */584584-585585-static void586586-rtas_pci_slot_reset(struct pci_dn *pdn, int state)587587-{588588- int config_addr;589589- int rc;590590-591591- BUG_ON (pdn==NULL); 592592-593593- if (!pdn->phb) {594594- printk (KERN_WARNING "EEH: in slot reset, device node %s has no phb\n",595595- pdn->node->full_name);596596- return;597597- }598598-599599- /* Use PE configuration address, if present */600600- config_addr = pdn->eeh_config_addr;601601- if (pdn->eeh_pe_config_addr)602602- config_addr = pdn->eeh_pe_config_addr;603603-604604- rc = rtas_call(ibm_set_slot_reset, 4, 1, NULL,605605- config_addr,606606- BUID_HI(pdn->phb->buid),607607- BUID_LO(pdn->phb->buid),608608- state);609609-610610- /* Fundamental-reset not supported on this PE, try hot-reset */611611- if (rc == -8 && state == 3) {612612- rc = rtas_call(ibm_set_slot_reset, 4, 1, NULL,613613- config_addr,614614- BUID_HI(pdn->phb->buid),615615- BUID_LO(pdn->phb->buid), 1);616616- if (rc)617617- printk(KERN_WARNING618618- "EEH: Unable to reset the failed slot,"619619- " #RST=%d dn=%s\n",620620- rc, pdn->node->full_name);621621- }622622-}623623-624624-/**625694 * pcibios_set_pcie_slot_reset - Set PCI-E reset state626626- * @dev: pci device struct627627- * @state: reset state to enter695695+ * @dev: pci device struct696696+ * @state: reset state to enter628697 *629698 * Return value:630699 * 0 if success631631- **/700700+ */632701int pcibios_set_pcie_reset_state(struct pci_dev *dev, enum pcie_reset_state state)633702{634703 struct device_node *dn = pci_device_to_OF_node(dev);635635- struct pci_dn *pdn = PCI_DN(dn);636704637705 switch (state) {638706 case pcie_deassert_reset:639639- rtas_pci_slot_reset(pdn, 0);707707+ eeh_ops->reset(dn, EEH_RESET_DEACTIVATE);640708 break;641709 case pcie_hot_reset:642642- rtas_pci_slot_reset(pdn, 1);710710+ eeh_ops->reset(dn, EEH_RESET_HOT);643711 break;644712 case pcie_warm_reset:645645- rtas_pci_slot_reset(pdn, 3);713713+ eeh_ops->reset(dn, EEH_RESET_FUNDAMENTAL);646714 break;647715 default:648716 return -EINVAL;···591781}592782593783/**594594- * rtas_set_slot_reset -- assert the pci #RST line for 1/4 second595595- * @pdn: pci device node to be reset.784784+ * __eeh_set_pe_freset - Check the required reset for child devices785785+ * @parent: parent device786786+ * @freset: return value787787+ *788788+ * Each device might have its preferred reset type: fundamental or789789+ * hot reset. The routine is used to collect the information from790790+ * the child devices so that they could be reset accordingly.596791 */792792+void __eeh_set_pe_freset(struct device_node *parent, unsigned int *freset)793793+{794794+ struct device_node *dn;597795598598-static void __rtas_set_slot_reset(struct pci_dn *pdn)796796+ for_each_child_of_node(parent, dn) {797797+ if (of_node_to_eeh_dev(dn)) {798798+ struct pci_dev *dev = of_node_to_eeh_dev(dn)->pdev;799799+800800+ if (dev && dev->driver)801801+ *freset |= dev->needs_freset;802802+803803+ __eeh_set_pe_freset(dn, freset);804804+ }805805+ }806806+}807807+808808+/**809809+ * eeh_set_pe_freset - Check the required reset for the indicated device and its children810810+ * @dn: parent device811811+ * @freset: return value812812+ *813813+ * Each device might have its preferred reset type: fundamental or814814+ * hot reset. The routine is used to collected the information for815815+ * the indicated device and its children so that the bunch of the816816+ * devices could be reset properly.817817+ */818818+void eeh_set_pe_freset(struct device_node *dn, unsigned int *freset)819819+{820820+ struct pci_dev *dev;821821+ dn = eeh_find_device_pe(dn);822822+823823+ /* Back up one, since config addrs might be shared */824824+ if (!pcibios_find_pci_bus(dn) && of_node_to_eeh_dev(dn->parent))825825+ dn = dn->parent;826826+827827+ dev = of_node_to_eeh_dev(dn)->pdev;828828+ if (dev)829829+ *freset |= dev->needs_freset;830830+831831+ __eeh_set_pe_freset(dn, freset);832832+}833833+834834+/**835835+ * eeh_reset_pe_once - Assert the pci #RST line for 1/4 second836836+ * @edev: pci device node to be reset.837837+ *838838+ * Assert the PCI #RST line for 1/4 second.839839+ */840840+static void eeh_reset_pe_once(struct eeh_dev *edev)599841{600842 unsigned int freset = 0;843843+ struct device_node *dn = eeh_dev_to_of_node(edev);601844602845 /* Determine type of EEH reset required for603846 * Partitionable Endpoint, a hot-reset (1)···658795 * A fundamental reset required by any device under659796 * Partitionable Endpoint trumps hot-reset.660797 */661661- eeh_set_pe_freset(pdn->node, &freset);798798+ eeh_set_pe_freset(dn, &freset);662799663800 if (freset)664664- rtas_pci_slot_reset(pdn, 3);801801+ eeh_ops->reset(dn, EEH_RESET_FUNDAMENTAL);665802 else666666- rtas_pci_slot_reset(pdn, 1);803803+ eeh_ops->reset(dn, EEH_RESET_HOT);667804668805 /* The PCI bus requires that the reset be held high for at least669669- * a 100 milliseconds. We wait a bit longer 'just in case'. */670670-806806+ * a 100 milliseconds. We wait a bit longer 'just in case'.807807+ */671808#define PCI_BUS_RST_HOLD_TIME_MSEC 250672672- msleep (PCI_BUS_RST_HOLD_TIME_MSEC);809809+ msleep(PCI_BUS_RST_HOLD_TIME_MSEC);673810674811 /* We might get hit with another EEH freeze as soon as the 675812 * pci slot reset line is dropped. Make sure we don't miss676676- * these, and clear the flag now. */677677- eeh_clear_slot (pdn->node, EEH_MODE_ISOLATED);813813+ * these, and clear the flag now.814814+ */815815+ eeh_clear_slot(dn, EEH_MODE_ISOLATED);678816679679- rtas_pci_slot_reset (pdn, 0);817817+ eeh_ops->reset(dn, EEH_RESET_DEACTIVATE);680818681819 /* After a PCI slot has been reset, the PCI Express spec requires682820 * a 1.5 second idle time for the bus to stabilize, before starting683683- * up traffic. */821821+ * up traffic.822822+ */684823#define PCI_BUS_SETTLE_TIME_MSEC 1800685685- msleep (PCI_BUS_SETTLE_TIME_MSEC);824824+ msleep(PCI_BUS_SETTLE_TIME_MSEC);686825}687826688688-int rtas_set_slot_reset(struct pci_dn *pdn)827827+/**828828+ * eeh_reset_pe - Reset the indicated PE829829+ * @edev: PCI device associated EEH device830830+ *831831+ * This routine should be called to reset indicated device, including832832+ * PE. A PE might include multiple PCI devices and sometimes PCI bridges833833+ * might be involved as well.834834+ */835835+int eeh_reset_pe(struct eeh_dev *edev)689836{690837 int i, rc;838838+ struct device_node *dn = eeh_dev_to_of_node(edev);691839692840 /* Take three shots at resetting the bus */693841 for (i=0; i<3; i++) {694694- __rtas_set_slot_reset(pdn);842842+ eeh_reset_pe_once(edev);695843696696- rc = eeh_wait_for_slot_status(pdn, PCI_BUS_RESET_WAIT_MSEC);697697- if (rc == 0)844844+ rc = eeh_ops->wait_state(dn, PCI_BUS_RESET_WAIT_MSEC);845845+ if (rc == (EEH_STATE_MMIO_ACTIVE | EEH_STATE_DMA_ACTIVE))698846 return 0;699847700848 if (rc < 0) {701849 printk(KERN_ERR "EEH: unrecoverable slot failure %s\n",702702- pdn->node->full_name);850850+ dn->full_name);703851 return -1;704852 }705853 printk(KERN_ERR "EEH: bus reset %d failed on slot %s, rc=%d\n",706706- i+1, pdn->node->full_name, rc);854854+ i+1, dn->full_name, rc);707855 }708856709857 return -1;710858}711859712712-/* ------------------------------------------------------- */713860/** Save and restore of PCI BARs714861 *715862 * Although firmware will set up BARs during boot, it doesn't···729856 */730857731858/**732732- * __restore_bars - Restore the Base Address Registers733733- * @pdn: pci device node859859+ * eeh_restore_one_device_bars - Restore the Base Address Registers for one device860860+ * @edev: PCI device associated EEH device734861 *735862 * Loads the PCI configuration space base address registers,736863 * the expansion ROM base address, the latency timer, and etc.737864 * from the saved values in the device node.738865 */739739-static inline void __restore_bars (struct pci_dn *pdn)866866+static inline void eeh_restore_one_device_bars(struct eeh_dev *edev)740867{741868 int i;742869 u32 cmd;870870+ struct device_node *dn = eeh_dev_to_of_node(edev);743871744744- if (NULL==pdn->phb) return;872872+ if (!edev->phb)873873+ return;874874+745875 for (i=4; i<10; i++) {746746- rtas_write_config(pdn, i*4, 4, pdn->config_space[i]);876876+ eeh_ops->write_config(dn, i*4, 4, edev->config_space[i]);747877 }748878749879 /* 12 == Expansion ROM Address */750750- rtas_write_config(pdn, 12*4, 4, pdn->config_space[12]);880880+ eeh_ops->write_config(dn, 12*4, 4, edev->config_space[12]);751881752882#define BYTE_SWAP(OFF) (8*((OFF)/4)+3-(OFF))753753-#define SAVED_BYTE(OFF) (((u8 *)(pdn->config_space))[BYTE_SWAP(OFF)])883883+#define SAVED_BYTE(OFF) (((u8 *)(edev->config_space))[BYTE_SWAP(OFF)])754884755755- rtas_write_config (pdn, PCI_CACHE_LINE_SIZE, 1,885885+ eeh_ops->write_config(dn, PCI_CACHE_LINE_SIZE, 1,756886 SAVED_BYTE(PCI_CACHE_LINE_SIZE));757887758758- rtas_write_config (pdn, PCI_LATENCY_TIMER, 1,888888+ eeh_ops->write_config(dn, PCI_LATENCY_TIMER, 1,759889 SAVED_BYTE(PCI_LATENCY_TIMER));760890761891 /* max latency, min grant, interrupt pin and line */762762- rtas_write_config(pdn, 15*4, 4, pdn->config_space[15]);892892+ eeh_ops->write_config(dn, 15*4, 4, edev->config_space[15]);763893764894 /* Restore PERR & SERR bits, some devices require it,765765- don't touch the other command bits */766766- rtas_read_config(pdn, PCI_COMMAND, 4, &cmd);767767- if (pdn->config_space[1] & PCI_COMMAND_PARITY)895895+ * don't touch the other command bits896896+ */897897+ eeh_ops->read_config(dn, PCI_COMMAND, 4, &cmd);898898+ if (edev->config_space[1] & PCI_COMMAND_PARITY)768899 cmd |= PCI_COMMAND_PARITY;769900 else770901 cmd &= ~PCI_COMMAND_PARITY;771771- if (pdn->config_space[1] & PCI_COMMAND_SERR)902902+ if (edev->config_space[1] & PCI_COMMAND_SERR)772903 cmd |= PCI_COMMAND_SERR;773904 else774905 cmd &= ~PCI_COMMAND_SERR;775775- rtas_write_config(pdn, PCI_COMMAND, 4, cmd);906906+ eeh_ops->write_config(dn, PCI_COMMAND, 4, cmd);776907}777908778909/**779779- * eeh_restore_bars - restore the PCI config space info910910+ * eeh_restore_bars - Restore the PCI config space info911911+ * @edev: EEH device780912 *781913 * This routine performs a recursive walk to the children782914 * of this device as well.783915 */784784-void eeh_restore_bars(struct pci_dn *pdn)916916+void eeh_restore_bars(struct eeh_dev *edev)785917{786918 struct device_node *dn;787787- if (!pdn) 919919+ if (!edev)788920 return;789921790790- if ((pdn->eeh_mode & EEH_MODE_SUPPORTED) && !IS_BRIDGE(pdn->class_code))791791- __restore_bars (pdn);922922+ if ((edev->mode & EEH_MODE_SUPPORTED) && !IS_BRIDGE(edev->class_code))923923+ eeh_restore_one_device_bars(edev);792924793793- for_each_child_of_node(pdn->node, dn)794794- eeh_restore_bars (PCI_DN(dn));925925+ for_each_child_of_node(eeh_dev_to_of_node(edev), dn)926926+ eeh_restore_bars(of_node_to_eeh_dev(dn));795927}796928797929/**798798- * eeh_save_bars - save device bars930930+ * eeh_save_bars - Save device bars931931+ * @edev: PCI device associated EEH device799932 *800933 * Save the values of the device bars. Unlike the restore801934 * routine, this routine is *not* recursive. This is because802935 * PCI devices are added individually; but, for the restore,803936 * an entire slot is reset at a time.804937 */805805-static void eeh_save_bars(struct pci_dn *pdn)938938+static void eeh_save_bars(struct eeh_dev *edev)806939{807940 int i;941941+ struct device_node *dn;808942809809- if (!pdn )943943+ if (!edev)810944 return;945945+ dn = eeh_dev_to_of_node(edev);811946812947 for (i = 0; i < 16; i++)813813- rtas_read_config(pdn, i * 4, 4, &pdn->config_space[i]);948948+ eeh_ops->read_config(dn, i * 4, 4, &edev->config_space[i]);814949}815950816816-void817817-rtas_configure_bridge(struct pci_dn *pdn)818818-{819819- int config_addr;820820- int rc;821821- int token;822822-823823- /* Use PE configuration address, if present */824824- config_addr = pdn->eeh_config_addr;825825- if (pdn->eeh_pe_config_addr)826826- config_addr = pdn->eeh_pe_config_addr;827827-828828- /* Use new configure-pe function, if supported */829829- if (ibm_configure_pe != RTAS_UNKNOWN_SERVICE)830830- token = ibm_configure_pe;831831- else832832- token = ibm_configure_bridge;833833-834834- rc = rtas_call(token, 3, 1, NULL,835835- config_addr,836836- BUID_HI(pdn->phb->buid),837837- BUID_LO(pdn->phb->buid));838838- if (rc) {839839- printk (KERN_WARNING "EEH: Unable to configure device bridge (%d) for %s\n",840840- rc, pdn->node->full_name);841841- }842842-}843843-844844-/* ------------------------------------------------------------- */845845-/* The code below deals with enabling EEH for devices during the846846- * early boot sequence. EEH must be enabled before any PCI probing847847- * can be done.951951+/**952952+ * eeh_early_enable - Early enable EEH on the indicated device953953+ * @dn: device node954954+ * @data: BUID955955+ *956956+ * Enable EEH functionality on the specified PCI device. The function957957+ * is expected to be called before real PCI probing is done. However,958958+ * the PHBs have been initialized at this point.848959 */849849-850850-#define EEH_ENABLE 1851851-852852-struct eeh_early_enable_info {853853- unsigned int buid_hi;854854- unsigned int buid_lo;855855-};856856-857857-static int get_pe_addr (int config_addr,858858- struct eeh_early_enable_info *info)960960+static void *eeh_early_enable(struct device_node *dn, void *data)859961{860860- unsigned int rets[3];861861- int ret;862862-863863- /* Use latest config-addr token on power6 */864864- if (ibm_get_config_addr_info2 != RTAS_UNKNOWN_SERVICE) {865865- /* Make sure we have a PE in hand */866866- ret = rtas_call (ibm_get_config_addr_info2, 4, 2, rets,867867- config_addr, info->buid_hi, info->buid_lo, 1);868868- if (ret || (rets[0]==0))869869- return 0;870870-871871- ret = rtas_call (ibm_get_config_addr_info2, 4, 2, rets,872872- config_addr, info->buid_hi, info->buid_lo, 0);873873- if (ret)874874- return 0;875875- return rets[0];876876- }877877-878878- /* Use older config-addr token on power5 */879879- if (ibm_get_config_addr_info != RTAS_UNKNOWN_SERVICE) {880880- ret = rtas_call (ibm_get_config_addr_info, 4, 2, rets,881881- config_addr, info->buid_hi, info->buid_lo, 0);882882- if (ret)883883- return 0;884884- return rets[0];885885- }886886- return 0;887887-}888888-889889-/* Enable eeh for the given device node. */890890-static void *early_enable_eeh(struct device_node *dn, void *data)891891-{892892- unsigned int rets[3];893893- struct eeh_early_enable_info *info = data;894962 int ret;895963 const u32 *class_code = of_get_property(dn, "class-code", NULL);896964 const u32 *vendor_id = of_get_property(dn, "vendor-id", NULL);897965 const u32 *device_id = of_get_property(dn, "device-id", NULL);898966 const u32 *regs;899967 int enable;900900- struct pci_dn *pdn = PCI_DN(dn);968968+ struct eeh_dev *edev = of_node_to_eeh_dev(dn);901969902902- pdn->class_code = 0;903903- pdn->eeh_mode = 0;904904- pdn->eeh_check_count = 0;905905- pdn->eeh_freeze_count = 0;906906- pdn->eeh_false_positives = 0;970970+ edev->class_code = 0;971971+ edev->mode = 0;972972+ edev->check_count = 0;973973+ edev->freeze_count = 0;974974+ edev->false_positives = 0;907975908976 if (!of_device_is_available(dn))909977 return NULL;···85510418561042 /* There is nothing to check on PCI to ISA bridges */8571043 if (dn->type && !strcmp(dn->type, "isa")) {858858- pdn->eeh_mode |= EEH_MODE_NOCHECK;10441044+ edev->mode |= EEH_MODE_NOCHECK;8591045 return NULL;8601046 }861861- pdn->class_code = *class_code;10471047+ edev->class_code = *class_code;86210488631049 /* Ok... see if this device supports EEH. Some do, some don't,864864- * and the only way to find out is to check each and every one. */10501050+ * and the only way to find out is to check each and every one.10511051+ */8651052 regs = of_get_property(dn, "reg", NULL);8661053 if (regs) {8671054 /* First register entry is addr (00BBSS00) */8681055 /* Try to enable eeh */869869- ret = rtas_call(ibm_set_eeh_option, 4, 1, NULL,870870- regs[0], info->buid_hi, info->buid_lo,871871- EEH_ENABLE);10561056+ ret = eeh_ops->set_option(dn, EEH_OPT_ENABLE);87210578731058 enable = 0;8741059 if (ret == 0) {875875- pdn->eeh_config_addr = regs[0];10601060+ edev->config_addr = regs[0];87610618771062 /* If the newer, better, ibm,get-config-addr-info is supported, 878878- * then use that instead. */879879- pdn->eeh_pe_config_addr = get_pe_addr(pdn->eeh_config_addr, info);10631063+ * then use that instead.10641064+ */10651065+ edev->pe_config_addr = eeh_ops->get_pe_addr(dn);88010668811067 /* Some older systems (Power4) allow the8821068 * ibm,set-eeh-option call to succeed even on nodes8831069 * where EEH is not supported. Verify support884884- * explicitly. */885885- ret = read_slot_reset_state(pdn, rets);886886- if ((ret == 0) && (rets[1] == 1))10701070+ * explicitly.10711071+ */10721072+ ret = eeh_ops->get_state(dn, NULL);10731073+ if (ret > 0 && ret != EEH_STATE_NOT_SUPPORT)8871074 enable = 1;8881075 }88910768901077 if (enable) {8911078 eeh_subsystem_enabled = 1;892892- pdn->eeh_mode |= EEH_MODE_SUPPORTED;10791079+ edev->mode |= EEH_MODE_SUPPORTED;89310808941081 pr_debug("EEH: %s: eeh enabled, config=%x pe_config=%x\n",895895- dn->full_name, pdn->eeh_config_addr,896896- pdn->eeh_pe_config_addr);10821082+ dn->full_name, edev->config_addr,10831083+ edev->pe_config_addr);8971084 } else {89810858991086 /* This device doesn't support EEH, but it may have an900900- * EEH parent, in which case we mark it as supported. */901901- if (dn->parent && PCI_DN(dn->parent)902902- && (PCI_DN(dn->parent)->eeh_mode & EEH_MODE_SUPPORTED)) {10871087+ * EEH parent, in which case we mark it as supported.10881088+ */10891089+ if (dn->parent && of_node_to_eeh_dev(dn->parent) &&10901090+ (of_node_to_eeh_dev(dn->parent)->mode & EEH_MODE_SUPPORTED)) {9031091 /* Parent supports EEH. */904904- pdn->eeh_mode |= EEH_MODE_SUPPORTED;905905- pdn->eeh_config_addr = PCI_DN(dn->parent)->eeh_config_addr;10921092+ edev->mode |= EEH_MODE_SUPPORTED;10931093+ edev->config_addr = of_node_to_eeh_dev(dn->parent)->config_addr;9061094 return NULL;9071095 }9081096 }···9131097 dn->full_name);9141098 }9151099916916- eeh_save_bars(pdn);11001100+ eeh_save_bars(edev);9171101 return NULL;9181102}9191103920920-/*11041104+/**11051105+ * eeh_ops_register - Register platform dependent EEH operations11061106+ * @ops: platform dependent EEH operations11071107+ *11081108+ * Register the platform dependent EEH operation callback11091109+ * functions. The platform should call this function before11101110+ * any other EEH operations.11111111+ */11121112+int __init eeh_ops_register(struct eeh_ops *ops)11131113+{11141114+ if (!ops->name) {11151115+ pr_warning("%s: Invalid EEH ops name for %p\n",11161116+ __func__, ops);11171117+ return -EINVAL;11181118+ }11191119+11201120+ if (eeh_ops && eeh_ops != ops) {11211121+ pr_warning("%s: EEH ops of platform %s already existing (%s)\n",11221122+ __func__, eeh_ops->name, ops->name);11231123+ return -EEXIST;11241124+ }11251125+11261126+ eeh_ops = ops;11271127+11281128+ return 0;11291129+}11301130+11311131+/**11321132+ * eeh_ops_unregister - Unreigster platform dependent EEH operations11331133+ * @name: name of EEH platform operations11341134+ *11351135+ * Unregister the platform dependent EEH operation callback11361136+ * functions.11371137+ */11381138+int __exit eeh_ops_unregister(const char *name)11391139+{11401140+ if (!name || !strlen(name)) {11411141+ pr_warning("%s: Invalid EEH ops name\n",11421142+ __func__);11431143+ return -EINVAL;11441144+ }11451145+11461146+ if (eeh_ops && !strcmp(eeh_ops->name, name)) {11471147+ eeh_ops = NULL;11481148+ return 0;11491149+ }11501150+11511151+ return -EEXIST;11521152+}11531153+11541154+/**11551155+ * eeh_init - EEH initialization11561156+ *9211157 * Initialize EEH by trying to enable it for all of the adapters in the system.9221158 * As a side effect we can determine here if eeh is supported at all.9231159 * Note that we leave EEH on so failed config cycles won't cause a machine···9851117void __init eeh_init(void)9861118{9871119 struct device_node *phb, *np;988988- struct eeh_early_enable_info info;11201120+ int ret;11211121+11221122+ /* call platform initialization function */11231123+ if (!eeh_ops) {11241124+ pr_warning("%s: Platform EEH operation not found\n",11251125+ __func__);11261126+ return;11271127+ } else if ((ret = eeh_ops->init())) {11281128+ pr_warning("%s: Failed to call platform init function (%d)\n",11291129+ __func__, ret);11301130+ return;11311131+ }98911329901133 raw_spin_lock_init(&confirm_error_lock);991991- spin_lock_init(&slot_errbuf_lock);99211349931135 np = of_find_node_by_path("/rtas");9941136 if (np == NULL)9951137 return;996996-997997- ibm_set_eeh_option = rtas_token("ibm,set-eeh-option");998998- ibm_set_slot_reset = rtas_token("ibm,set-slot-reset");999999- ibm_read_slot_reset_state2 = rtas_token("ibm,read-slot-reset-state2");10001000- ibm_read_slot_reset_state = rtas_token("ibm,read-slot-reset-state");10011001- ibm_slot_error_detail = rtas_token("ibm,slot-error-detail");10021002- ibm_get_config_addr_info = rtas_token("ibm,get-config-addr-info");10031003- ibm_get_config_addr_info2 = rtas_token("ibm,get-config-addr-info2");10041004- ibm_configure_bridge = rtas_token ("ibm,configure-bridge");10051005- ibm_configure_pe = rtas_token("ibm,configure-pe");10061006-10071007- if (ibm_set_eeh_option == RTAS_UNKNOWN_SERVICE)10081008- return;10091009-10101010- eeh_error_buf_size = rtas_token("rtas-error-log-max");10111011- if (eeh_error_buf_size == RTAS_UNKNOWN_SERVICE) {10121012- eeh_error_buf_size = 1024;10131013- }10141014- if (eeh_error_buf_size > RTAS_ERROR_LOG_MAX) {10151015- printk(KERN_WARNING "EEH: rtas-error-log-max is bigger than allocated "10161016- "buffer ! (%d vs %d)", eeh_error_buf_size, RTAS_ERROR_LOG_MAX);10171017- eeh_error_buf_size = RTAS_ERROR_LOG_MAX;10181018- }1019113810201139 /* Enable EEH for all adapters. Note that eeh requires buid's */10211140 for (phb = of_find_node_by_name(NULL, "pci"); phb;···10101155 unsigned long buid;1011115610121157 buid = get_phb_buid(phb);10131013- if (buid == 0 || PCI_DN(phb) == NULL)11581158+ if (buid == 0 || !of_node_to_eeh_dev(phb))10141159 continue;1015116010161016- info.buid_lo = BUID_LO(buid);10171017- info.buid_hi = BUID_HI(buid);10181018- traverse_pci_devices(phb, early_enable_eeh, &info);11611161+ traverse_pci_devices(phb, eeh_early_enable, NULL);10191162 }1020116310211164 if (eeh_subsystem_enabled)···10231170}1024117110251172/**10261026- * eeh_add_device_early - enable EEH for the indicated device_node11731173+ * eeh_add_device_early - Enable EEH for the indicated device_node10271174 * @dn: device node for which to set up EEH10281175 *10291176 * This routine must be used to perform EEH initialization for PCI···10371184static void eeh_add_device_early(struct device_node *dn)10381185{10391186 struct pci_controller *phb;10401040- struct eeh_early_enable_info info;1041118710421042- if (!dn || !PCI_DN(dn))11881188+ if (!dn || !of_node_to_eeh_dev(dn))10431189 return;10441044- phb = PCI_DN(dn)->phb;11901190+ phb = of_node_to_eeh_dev(dn)->phb;1045119110461192 /* USB Bus children of PCI devices will not have BUID's */10471193 if (NULL == phb || 0 == phb->buid)10481194 return;1049119510501050- info.buid_hi = BUID_HI(phb->buid);10511051- info.buid_lo = BUID_LO(phb->buid);10521052- early_enable_eeh(dn, &info);11961196+ eeh_early_enable(dn, NULL);10531197}1054119811991199+/**12001200+ * eeh_add_device_tree_early - Enable EEH for the indicated device12011201+ * @dn: device node12021202+ *12031203+ * This routine must be used to perform EEH initialization for the12041204+ * indicated PCI device that was added after system boot (e.g.12051205+ * hotplug, dlpar).12061206+ */10551207void eeh_add_device_tree_early(struct device_node *dn)10561208{10571209 struct device_node *sib;···10681210EXPORT_SYMBOL_GPL(eeh_add_device_tree_early);1069121110701212/**10711071- * eeh_add_device_late - perform EEH initialization for the indicated pci device12131213+ * eeh_add_device_late - Perform EEH initialization for the indicated pci device10721214 * @dev: pci device for which to set up EEH10731215 *10741216 * This routine must be used to complete EEH initialization for PCI···10771219static void eeh_add_device_late(struct pci_dev *dev)10781220{10791221 struct device_node *dn;10801080- struct pci_dn *pdn;12221222+ struct eeh_dev *edev;1081122310821224 if (!dev || !eeh_subsystem_enabled)10831225 return;···10851227 pr_debug("EEH: Adding device %s\n", pci_name(dev));1086122810871229 dn = pci_device_to_OF_node(dev);10881088- pdn = PCI_DN(dn);10891089- if (pdn->pcidev == dev) {12301230+ edev = pci_dev_to_eeh_dev(dev);12311231+ if (edev->pdev == dev) {10901232 pr_debug("EEH: Already referenced !\n");10911233 return;10921234 }10931093- WARN_ON(pdn->pcidev);12351235+ WARN_ON(edev->pdev);1094123610951095- pci_dev_get (dev);10961096- pdn->pcidev = dev;12371237+ pci_dev_get(dev);12381238+ edev->pdev = dev;12391239+ dev->dev.archdata.edev = edev;1097124010981241 pci_addr_cache_insert_device(dev);10991242 eeh_sysfs_add_device(dev);11001243}1101124412451245+/**12461246+ * eeh_add_device_tree_late - Perform EEH initialization for the indicated PCI bus12471247+ * @bus: PCI bus12481248+ *12491249+ * This routine must be used to perform EEH initialization for PCI12501250+ * devices which are attached to the indicated PCI bus. The PCI bus12511251+ * is added after system boot through hotplug or dlpar.12521252+ */11021253void eeh_add_device_tree_late(struct pci_bus *bus)11031254{11041255 struct pci_dev *dev;···11241257EXPORT_SYMBOL_GPL(eeh_add_device_tree_late);1125125811261259/**11271127- * eeh_remove_device - undo EEH setup for the indicated pci device12601260+ * eeh_remove_device - Undo EEH setup for the indicated pci device11281261 * @dev: pci device to be removed11291262 *11301263 * This routine should be called when a device is removed from···11351268 */11361269static void eeh_remove_device(struct pci_dev *dev)11371270{11381138- struct device_node *dn;12711271+ struct eeh_dev *edev;12721272+11391273 if (!dev || !eeh_subsystem_enabled)11401274 return;12751275+ edev = pci_dev_to_eeh_dev(dev);1141127611421277 /* Unregister the device with the EEH/PCI address search system */11431278 pr_debug("EEH: Removing device %s\n", pci_name(dev));1144127911451145- dn = pci_device_to_OF_node(dev);11461146- if (PCI_DN(dn)->pcidev == NULL) {12801280+ if (!edev || !edev->pdev) {11471281 pr_debug("EEH: Not referenced !\n");11481282 return;11491283 }11501150- PCI_DN(dn)->pcidev = NULL;11511151- pci_dev_put (dev);12841284+ edev->pdev = NULL;12851285+ dev->dev.archdata.edev = NULL;12861286+ pci_dev_put(dev);1152128711531288 pci_addr_cache_remove_device(dev);11541289 eeh_sysfs_remove_device(dev);11551290}1156129112921292+/**12931293+ * eeh_remove_bus_device - Undo EEH setup for the indicated PCI device12941294+ * @dev: PCI device12951295+ *12961296+ * This routine must be called when a device is removed from the12971297+ * running system through hotplug or dlpar. The corresponding12981298+ * PCI address cache will be removed.12991299+ */11571300void eeh_remove_bus_device(struct pci_dev *dev)11581301{11591302 struct pci_bus *bus = dev->subordinate;···11821305{11831306 if (0 == eeh_subsystem_enabled) {11841307 seq_printf(m, "EEH Subsystem is globally disabled\n");11851185- seq_printf(m, "eeh_total_mmio_ffs=%ld\n", total_mmio_ffs);13081308+ seq_printf(m, "eeh_total_mmio_ffs=%llu\n", eeh_stats.total_mmio_ffs);11861309 } else {11871310 seq_printf(m, "EEH Subsystem is enabled\n");11881311 seq_printf(m,11891189- "no device=%ld\n"11901190- "no device node=%ld\n"11911191- "no config address=%ld\n"11921192- "check not wanted=%ld\n"11931193- "eeh_total_mmio_ffs=%ld\n"11941194- "eeh_false_positives=%ld\n"11951195- "eeh_slot_resets=%ld\n",11961196- no_device, no_dn, no_cfg_addr, 11971197- ignored_check, total_mmio_ffs, 11981198- false_positives,11991199- slot_resets);13121312+ "no device=%llu\n"13131313+ "no device node=%llu\n"13141314+ "no config address=%llu\n"13151315+ "check not wanted=%llu\n"13161316+ "eeh_total_mmio_ffs=%llu\n"13171317+ "eeh_false_positives=%llu\n"13181318+ "eeh_slot_resets=%llu\n",13191319+ eeh_stats.no_device,13201320+ eeh_stats.no_dn,13211321+ eeh_stats.no_cfg_addr,13221322+ eeh_stats.ignored_check,13231323+ eeh_stats.total_mmio_ffs,13241324+ eeh_stats.false_positives,13251325+ eeh_stats.slot_resets);12001326 }1201132712021328 return 0;
+27-17
arch/powerpc/platforms/pseries/eeh_cache.c
···11/*22- * eeh_cache.c32 * PCI address cache; allows the lookup of PCI devices based on I/O address43 *54 * Copyright IBM Corporation 2004···4647 * than any hash algo I could think of for this problem, even4748 * with the penalty of slow pointer chases for d-cache misses).4849 */4949-struct pci_io_addr_range5050-{5050+struct pci_io_addr_range {5151 struct rb_node rb_node;5252 unsigned long addr_lo;5353 unsigned long addr_hi;···5456 unsigned int flags;5557};56585757-static struct pci_io_addr_cache5858-{5959+static struct pci_io_addr_cache {5960 struct rb_root rb_root;6061 spinlock_t piar_lock;6162} pci_io_addr_cache_root;62636363-static inline struct pci_dev *__pci_get_device_by_addr(unsigned long addr)6464+static inline struct pci_dev *__pci_addr_cache_get_device(unsigned long addr)6465{6566 struct rb_node *n = pci_io_addr_cache_root.rb_root.rb_node;6667···8386}84878588/**8686- * pci_get_device_by_addr - Get device, given only address8989+ * pci_addr_cache_get_device - Get device, given only address8790 * @addr: mmio (PIO) phys address or i/o port number8891 *8992 * Given an mmio phys address, or a port number, find a pci device···9295 * from zero (that is, they do *not* have pci_io_addr added in).9396 * It is safe to call this function within an interrupt.9497 */9595-struct pci_dev *pci_get_device_by_addr(unsigned long addr)9898+struct pci_dev *pci_addr_cache_get_device(unsigned long addr)9699{97100 struct pci_dev *dev;98101 unsigned long flags;99102100103 spin_lock_irqsave(&pci_io_addr_cache_root.piar_lock, flags);101101- dev = __pci_get_device_by_addr(addr);104104+ dev = __pci_addr_cache_get_device(addr);102105 spin_unlock_irqrestore(&pci_io_addr_cache_root.piar_lock, flags);103106 return dev;104107}···163166164167#ifdef DEBUG165168 printk(KERN_DEBUG "PIAR: insert range=[%lx:%lx] dev=%s\n",166166- alo, ahi, pci_name (dev));169169+ alo, ahi, pci_name(dev));167170#endif168171169172 rb_link_node(&piar->rb_node, parent, p);···175178static void __pci_addr_cache_insert_device(struct pci_dev *dev)176179{177180 struct device_node *dn;178178- struct pci_dn *pdn;181181+ struct eeh_dev *edev;179182 int i;180183181184 dn = pci_device_to_OF_node(dev);···184187 return;185188 }186189190190+ edev = of_node_to_eeh_dev(dn);191191+ if (!edev) {192192+ pr_warning("PCI: no EEH dev found for dn=%s\n",193193+ dn->full_name);194194+ return;195195+ }196196+187197 /* Skip any devices for which EEH is not enabled. */188188- pdn = PCI_DN(dn);189189- if (!(pdn->eeh_mode & EEH_MODE_SUPPORTED) ||190190- pdn->eeh_mode & EEH_MODE_NOCHECK) {198198+ if (!(edev->mode & EEH_MODE_SUPPORTED) ||199199+ edev->mode & EEH_MODE_NOCHECK) {191200#ifdef DEBUG192192- printk(KERN_INFO "PCI: skip building address cache for=%s - %s\n",193193- pci_name(dev), pdn->node->full_name);201201+ pr_info("PCI: skip building address cache for=%s - %s\n",202202+ pci_name(dev), dn->full_name);194203#endif195204 return;196205 }···287284void __init pci_addr_cache_build(void)288285{289286 struct device_node *dn;287287+ struct eeh_dev *edev;290288 struct pci_dev *dev = NULL;291289292290 spin_lock_init(&pci_io_addr_cache_root.piar_lock);···298294 dn = pci_device_to_OF_node(dev);299295 if (!dn)300296 continue;297297+298298+ edev = of_node_to_eeh_dev(dn);299299+ if (!edev)300300+ continue;301301+301302 pci_dev_get(dev); /* matching put is in eeh_remove_device() */302302- PCI_DN(dn)->pcidev = dev;303303+ dev->dev.archdata.edev = edev;304304+ edev->pdev = dev;303305304306 eeh_sysfs_add_device(dev);305307 }
+102
arch/powerpc/platforms/pseries/eeh_dev.c
···11+/*22+ * The file intends to implement dynamic creation of EEH device, which will33+ * be bound with OF node and PCI device simutaneously. The EEH devices would44+ * be foundamental information for EEH core components to work proerly. Besides,55+ * We have to support multiple situations where dynamic creation of EEH device66+ * is required:77+ *88+ * 1) Before PCI emunation starts, we need create EEH devices according to the99+ * PCI sensitive OF nodes.1010+ * 2) When PCI emunation is done, we need do the binding between PCI device and1111+ * the associated EEH device.1212+ * 3) DR (Dynamic Reconfiguration) would create PCI sensitive OF node. EEH device1313+ * will be created while PCI sensitive OF node is detected from DR.1414+ * 4) PCI hotplug needs redoing the binding between PCI device and EEH device. If1515+ * PHB is newly inserted, we also need create EEH devices accordingly.1616+ *1717+ * Copyright Benjamin Herrenschmidt & Gavin Shan, IBM Corporation 2012.1818+ *1919+ * This program is free software; you can redistribute it and/or modify2020+ * it under the terms of the GNU General Public License as published by2121+ * the Free Software Foundation; either version 2 of the License, or2222+ * (at your option) any later version.2323+ *2424+ * This program is distributed in the hope that it will be useful,2525+ * but WITHOUT ANY WARRANTY; without even the implied warranty of2626+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the2727+ * GNU General Public License for more details.2828+ *2929+ * You should have received a copy of the GNU General Public License3030+ * along with this program; if not, write to the Free Software3131+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA3232+ */3333+3434+#include <linux/export.h>3535+#include <linux/gfp.h>3636+#include <linux/init.h>3737+#include <linux/kernel.h>3838+#include <linux/pci.h>3939+#include <linux/string.h>4040+4141+#include <asm/pci-bridge.h>4242+#include <asm/ppc-pci.h>4343+4444+/**4545+ * eeh_dev_init - Create EEH device according to OF node4646+ * @dn: device node4747+ * @data: PHB4848+ *4949+ * It will create EEH device according to the given OF node. The function5050+ * might be called by PCI emunation, DR, PHB hotplug.5151+ */5252+void * __devinit eeh_dev_init(struct device_node *dn, void *data)5353+{5454+ struct pci_controller *phb = data;5555+ struct eeh_dev *edev;5656+5757+ /* Allocate EEH device */5858+ edev = zalloc_maybe_bootmem(sizeof(*edev), GFP_KERNEL);5959+ if (!edev) {6060+ pr_warning("%s: out of memory\n", __func__);6161+ return NULL;6262+ }6363+6464+ /* Associate EEH device with OF node */6565+ dn->edev = edev;6666+ edev->dn = dn;6767+ edev->phb = phb;6868+6969+ return NULL;7070+}7171+7272+/**7373+ * eeh_dev_phb_init_dynamic - Create EEH devices for devices included in PHB7474+ * @phb: PHB7575+ *7676+ * Scan the PHB OF node and its child association, then create the7777+ * EEH devices accordingly7878+ */7979+void __devinit eeh_dev_phb_init_dynamic(struct pci_controller *phb)8080+{8181+ struct device_node *dn = phb->dn;8282+8383+ /* EEH device for PHB */8484+ eeh_dev_init(dn, phb);8585+8686+ /* EEH devices for children OF nodes */8787+ traverse_pci_devices(dn, eeh_dev_init, phb);8888+}8989+9090+/**9191+ * eeh_dev_phb_init - Create EEH devices for devices included in existing PHBs9292+ *9393+ * Scan all the existing PHBs and create EEH devices for their OF9494+ * nodes and their children OF nodes9595+ */9696+void __init eeh_dev_phb_init(void)9797+{9898+ struct pci_controller *phb, *tmp;9999+100100+ list_for_each_entry_safe(phb, tmp, &hose_list, list_node)101101+ eeh_dev_phb_init_dynamic(phb);102102+}
+120-93
arch/powerpc/platforms/pseries/eeh_driver.c
···3333#include <asm/prom.h>3434#include <asm/rtas.h>35353636-3737-static inline const char * pcid_name (struct pci_dev *pdev)3636+/**3737+ * eeh_pcid_name - Retrieve name of PCI device driver3838+ * @pdev: PCI device3939+ *4040+ * This routine is used to retrieve the name of PCI device driver4141+ * if that's valid.4242+ */4343+static inline const char *eeh_pcid_name(struct pci_dev *pdev)3844{3945 if (pdev && pdev->dev.driver)4046 return pdev->dev.driver->name;···7064#endif71657266/**7373- * eeh_disable_irq - disable interrupt for the recovering device6767+ * eeh_disable_irq - Disable interrupt for the recovering device6868+ * @dev: PCI device6969+ *7070+ * This routine must be called when reporting temporary or permanent7171+ * error to the particular PCI device to disable interrupt of that7272+ * device. If the device has enabled MSI or MSI-X interrupt, we needn't7373+ * do real work because EEH should freeze DMA transfers for those PCI7474+ * devices encountering EEH errors, which includes MSI or MSI-X.7475 */7576static void eeh_disable_irq(struct pci_dev *dev)7677{7777- struct device_node *dn = pci_device_to_OF_node(dev);7878+ struct eeh_dev *edev = pci_dev_to_eeh_dev(dev);78797980 /* Don't disable MSI and MSI-X interrupts. They are8081 * effectively disabled by the DMA Stopped state8182 * when an EEH error occurs.8282- */8383+ */8384 if (dev->msi_enabled || dev->msix_enabled)8485 return;85868687 if (!irq_has_action(dev->irq))8788 return;88898989- PCI_DN(dn)->eeh_mode |= EEH_MODE_IRQ_DISABLED;9090+ edev->mode |= EEH_MODE_IRQ_DISABLED;9091 disable_irq_nosync(dev->irq);9192}92939394/**9494- * eeh_enable_irq - enable interrupt for the recovering device9595+ * eeh_enable_irq - Enable interrupt for the recovering device9696+ * @dev: PCI device9797+ *9898+ * This routine must be called to enable interrupt while failed9999+ * device could be resumed.95100 */96101static void eeh_enable_irq(struct pci_dev *dev)97102{9898- struct device_node *dn = pci_device_to_OF_node(dev);103103+ struct eeh_dev *edev = pci_dev_to_eeh_dev(dev);99104100100- if ((PCI_DN(dn)->eeh_mode) & EEH_MODE_IRQ_DISABLED) {101101- PCI_DN(dn)->eeh_mode &= ~EEH_MODE_IRQ_DISABLED;105105+ if ((edev->mode) & EEH_MODE_IRQ_DISABLED) {106106+ edev->mode &= ~EEH_MODE_IRQ_DISABLED;102107 enable_irq(dev->irq);103108 }104109}105110106106-/* ------------------------------------------------------- */107111/**108108- * eeh_report_error - report pci error to each device driver112112+ * eeh_report_error - Report pci error to each device driver113113+ * @dev: PCI device114114+ * @userdata: return value109115 * 110116 * Report an EEH error to each device driver, collect up and 111117 * merge the device driver responses. Cumulative response 112118 * passed back in "userdata".113119 */114114-115120static int eeh_report_error(struct pci_dev *dev, void *userdata)116121{117122 enum pci_ers_result rc, *res = userdata;···139122 !driver->err_handler->error_detected)140123 return 0;141124142142- rc = driver->err_handler->error_detected (dev, pci_channel_io_frozen);125125+ rc = driver->err_handler->error_detected(dev, pci_channel_io_frozen);143126144127 /* A driver that needs a reset trumps all others */145128 if (rc == PCI_ERS_RESULT_NEED_RESET) *res = rc;···149132}150133151134/**152152- * eeh_report_mmio_enabled - tell drivers that MMIO has been enabled135135+ * eeh_report_mmio_enabled - Tell drivers that MMIO has been enabled136136+ * @dev: PCI device137137+ * @userdata: return value153138 *154139 * Tells each device driver that IO ports, MMIO and config space I/O155140 * are now enabled. Collects up and merges the device driver responses.156141 * Cumulative response passed back in "userdata".157142 */158158-159143static int eeh_report_mmio_enabled(struct pci_dev *dev, void *userdata)160144{161145 enum pci_ers_result rc, *res = userdata;···167149 !driver->err_handler->mmio_enabled)168150 return 0;169151170170- rc = driver->err_handler->mmio_enabled (dev);152152+ rc = driver->err_handler->mmio_enabled(dev);171153172154 /* A driver that needs a reset trumps all others */173155 if (rc == PCI_ERS_RESULT_NEED_RESET) *res = rc;···177159}178160179161/**180180- * eeh_report_reset - tell device that slot has been reset162162+ * eeh_report_reset - Tell device that slot has been reset163163+ * @dev: PCI device164164+ * @userdata: return value165165+ *166166+ * This routine must be called while EEH tries to reset particular167167+ * PCI device so that the associated PCI device driver could take168168+ * some actions, usually to save data the driver needs so that the169169+ * driver can work again while the device is recovered.181170 */182182-183171static int eeh_report_reset(struct pci_dev *dev, void *userdata)184172{185173 enum pci_ers_result rc, *res = userdata;···212188}213189214190/**215215- * eeh_report_resume - tell device to resume normal operations191191+ * eeh_report_resume - Tell device to resume normal operations192192+ * @dev: PCI device193193+ * @userdata: return value194194+ *195195+ * This routine must be called to notify the device driver that it196196+ * could resume so that the device driver can do some initialization197197+ * to make the recovered device work again.216198 */217217-218199static int eeh_report_resume(struct pci_dev *dev, void *userdata)219200{220201 struct pci_driver *driver = dev->driver;···241212}242213243214/**244244- * eeh_report_failure - tell device driver that device is dead.215215+ * eeh_report_failure - Tell device driver that device is dead.216216+ * @dev: PCI device217217+ * @userdata: return value245218 *246219 * This informs the device driver that the device is permanently247220 * dead, and that no further recovery attempts will be made on it.248221 */249249-250222static int eeh_report_failure(struct pci_dev *dev, void *userdata)251223{252224 struct pci_driver *driver = dev->driver;···268238 return 0;269239}270240271271-/* ------------------------------------------------------- */272241/**273273- * handle_eeh_events -- reset a PCI device after hard lockup.242242+ * eeh_reset_device - Perform actual reset of a pci slot243243+ * @edev: PE associated EEH device244244+ * @bus: PCI bus corresponding to the isolcated slot274245 *275275- * pSeries systems will isolate a PCI slot if the PCI-Host276276- * bridge detects address or data parity errors, DMA's277277- * occurring to wild addresses (which usually happen due to278278- * bugs in device drivers or in PCI adapter firmware).279279- * Slot isolations also occur if #SERR, #PERR or other misc280280- * PCI-related errors are detected.281281- *282282- * Recovery process consists of unplugging the device driver283283- * (which generated hotplug events to userspace), then issuing284284- * a PCI #RST to the device, then reconfiguring the PCI config285285- * space for all bridges & devices under this slot, and then286286- * finally restarting the device drivers (which cause a second287287- * set of hotplug events to go out to userspace).246246+ * This routine must be called to do reset on the indicated PE.247247+ * During the reset, udev might be invoked because those affected248248+ * PCI devices will be removed and then added.288249 */289289-290290-/**291291- * eeh_reset_device() -- perform actual reset of a pci slot292292- * @bus: pointer to the pci bus structure corresponding293293- * to the isolated slot. A non-null value will294294- * cause all devices under the bus to be removed295295- * and then re-added.296296- * @pe_dn: pointer to a "Partionable Endpoint" device node.297297- * This is the top-level structure on which pci298298- * bus resets can be performed.299299- */300300-301301-static int eeh_reset_device (struct pci_dn *pe_dn, struct pci_bus *bus)250250+static int eeh_reset_device(struct eeh_dev *edev, struct pci_bus *bus)302251{303252 struct device_node *dn;304253 int cnt, rc;305254306255 /* pcibios will clear the counter; save the value */307307- cnt = pe_dn->eeh_freeze_count;256256+ cnt = edev->freeze_count;308257309258 if (bus)310259 pcibios_remove_pci_devices(bus);311260312261 /* Reset the pci controller. (Asserts RST#; resets config space).313262 * Reconfigure bridges and devices. Don't try to bring the system314314- * up if the reset failed for some reason. */315315- rc = rtas_set_slot_reset(pe_dn);263263+ * up if the reset failed for some reason.264264+ */265265+ rc = eeh_reset_pe(edev);316266 if (rc)317267 return rc;318268319319- /* Walk over all functions on this device. */320320- dn = pe_dn->node;321321- if (!pcibios_find_pci_bus(dn) && PCI_DN(dn->parent))269269+ /* Walk over all functions on this device. */270270+ dn = eeh_dev_to_of_node(edev);271271+ if (!pcibios_find_pci_bus(dn) && of_node_to_eeh_dev(dn->parent))322272 dn = dn->parent->child;323273324274 while (dn) {325325- struct pci_dn *ppe = PCI_DN(dn);275275+ struct eeh_dev *pedev = of_node_to_eeh_dev(dn);276276+326277 /* On Power4, always true because eeh_pe_config_addr=0 */327327- if (pe_dn->eeh_pe_config_addr == ppe->eeh_pe_config_addr) {328328- rtas_configure_bridge(ppe);329329- eeh_restore_bars(ppe);278278+ if (edev->pe_config_addr == pedev->pe_config_addr) {279279+ eeh_ops->configure_bridge(dn);280280+ eeh_restore_bars(pedev);330281 }331282 dn = dn->sibling;332283 }···319308 * potentially weird things happen.320309 */321310 if (bus) {322322- ssleep (5);311311+ ssleep(5);323312 pcibios_add_pci_devices(bus);324313 }325325- pe_dn->eeh_freeze_count = cnt;314314+ edev->freeze_count = cnt;326315327316 return 0;328317}···332321 */333322#define MAX_WAIT_FOR_RECOVERY 150334323335335-struct pci_dn * handle_eeh_events (struct eeh_event *event)324324+/**325325+ * eeh_handle_event - Reset a PCI device after hard lockup.326326+ * @event: EEH event327327+ *328328+ * While PHB detects address or data parity errors on particular PCI329329+ * slot, the associated PE will be frozen. Besides, DMA's occurring330330+ * to wild addresses (which usually happen due to bugs in device331331+ * drivers or in PCI adapter firmware) can cause EEH error. #SERR,332332+ * #PERR or other misc PCI-related errors also can trigger EEH errors.333333+ *334334+ * Recovery process consists of unplugging the device driver (which335335+ * generated hotplug events to userspace), then issuing a PCI #RST to336336+ * the device, then reconfiguring the PCI config space for all bridges337337+ * & devices under this slot, and then finally restarting the device338338+ * drivers (which cause a second set of hotplug events to go out to339339+ * userspace).340340+ */341341+struct eeh_dev *handle_eeh_events(struct eeh_event *event)336342{337343 struct device_node *frozen_dn;338338- struct pci_dn *frozen_pdn;344344+ struct eeh_dev *frozen_edev;339345 struct pci_bus *frozen_bus;340346 int rc = 0;341347 enum pci_ers_result result = PCI_ERS_RESULT_NONE;342348 const char *location, *pci_str, *drv_str, *bus_pci_str, *bus_drv_str;343349344344- frozen_dn = find_device_pe(event->dn);350350+ frozen_dn = eeh_find_device_pe(eeh_dev_to_of_node(event->edev));345351 if (!frozen_dn) {346346-347347- location = of_get_property(event->dn, "ibm,loc-code", NULL);352352+ location = of_get_property(eeh_dev_to_of_node(event->edev), "ibm,loc-code", NULL);348353 location = location ? location : "unknown";349354 printk(KERN_ERR "EEH: Error: Cannot find partition endpoint "350355 "for location=%s pci addr=%s\n",351351- location, eeh_pci_name(event->dev));356356+ location, eeh_pci_name(eeh_dev_to_pci_dev(event->edev)));352357 return NULL;353358 }354359···377350 * which was always an EADS pci bridge. In the new style,378351 * there might not be any EADS bridges, and even when there are,379352 * the firmware marks them as "EEH incapable". So another380380- * two-step is needed to find the pci bus.. */353353+ * two-step is needed to find the pci bus..354354+ */381355 if (!frozen_bus)382382- frozen_bus = pcibios_find_pci_bus (frozen_dn->parent);356356+ frozen_bus = pcibios_find_pci_bus(frozen_dn->parent);383357384358 if (!frozen_bus) {385359 printk(KERN_ERR "EEH: Cannot find PCI bus "···389361 return NULL;390362 }391363392392- frozen_pdn = PCI_DN(frozen_dn);393393- frozen_pdn->eeh_freeze_count++;364364+ frozen_edev = of_node_to_eeh_dev(frozen_dn);365365+ frozen_edev->freeze_count++;366366+ pci_str = eeh_pci_name(eeh_dev_to_pci_dev(event->edev));367367+ drv_str = eeh_pcid_name(eeh_dev_to_pci_dev(event->edev));394368395395- pci_str = eeh_pci_name(event->dev);396396- drv_str = pcid_name(event->dev);397397-398398- if (frozen_pdn->eeh_freeze_count > EEH_MAX_ALLOWED_FREEZES)369369+ if (frozen_edev->freeze_count > EEH_MAX_ALLOWED_FREEZES)399370 goto excess_failures;400371401372 printk(KERN_WARNING402373 "EEH: This PCI device has failed %d times in the last hour:\n",403403- frozen_pdn->eeh_freeze_count);374374+ frozen_edev->freeze_count);404375405405- if (frozen_pdn->pcidev) {406406- bus_pci_str = pci_name(frozen_pdn->pcidev);407407- bus_drv_str = pcid_name(frozen_pdn->pcidev);376376+ if (frozen_edev->pdev) {377377+ bus_pci_str = pci_name(frozen_edev->pdev);378378+ bus_drv_str = eeh_pcid_name(frozen_edev->pdev);408379 printk(KERN_WARNING409380 "EEH: Bus location=%s driver=%s pci addr=%s\n",410381 location, bus_drv_str, bus_pci_str);···422395 pci_walk_bus(frozen_bus, eeh_report_error, &result);423396424397 /* Get the current PCI slot state. This can take a long time,425425- * sometimes over 3 seconds for certain systems. */426426- rc = eeh_wait_for_slot_status (frozen_pdn, MAX_WAIT_FOR_RECOVERY*1000);427427- if (rc < 0) {398398+ * sometimes over 3 seconds for certain systems.399399+ */400400+ rc = eeh_ops->wait_state(eeh_dev_to_of_node(frozen_edev), MAX_WAIT_FOR_RECOVERY*1000);401401+ if (rc < 0 || rc == EEH_STATE_NOT_SUPPORT) {428402 printk(KERN_WARNING "EEH: Permanent failure\n");429403 goto hard_fail;430404 }···434406 * don't post the error log until after all dev drivers435407 * have been informed.436408 */437437- eeh_slot_error_detail(frozen_pdn, EEH_LOG_TEMP_FAILURE);409409+ eeh_slot_error_detail(frozen_edev, EEH_LOG_TEMP);438410439411 /* If all device drivers were EEH-unaware, then shut440412 * down all of the device drivers, and hope they441413 * go down willingly, without panicing the system.442414 */443415 if (result == PCI_ERS_RESULT_NONE) {444444- rc = eeh_reset_device(frozen_pdn, frozen_bus);416416+ rc = eeh_reset_device(frozen_edev, frozen_bus);445417 if (rc) {446418 printk(KERN_WARNING "EEH: Unable to reset, rc=%d\n", rc);447419 goto hard_fail;···450422451423 /* If all devices reported they can proceed, then re-enable MMIO */452424 if (result == PCI_ERS_RESULT_CAN_RECOVER) {453453- rc = rtas_pci_enable(frozen_pdn, EEH_THAW_MMIO);425425+ rc = eeh_pci_enable(frozen_edev, EEH_OPT_THAW_MMIO);454426455427 if (rc < 0)456428 goto hard_fail;···464436465437 /* If all devices reported they can proceed, then re-enable DMA */466438 if (result == PCI_ERS_RESULT_CAN_RECOVER) {467467- rc = rtas_pci_enable(frozen_pdn, EEH_THAW_DMA);439439+ rc = eeh_pci_enable(frozen_edev, EEH_OPT_THAW_DMA);468440469441 if (rc < 0)470442 goto hard_fail;···482454483455 /* If any device called out for a reset, then reset the slot */484456 if (result == PCI_ERS_RESULT_NEED_RESET) {485485- rc = eeh_reset_device(frozen_pdn, NULL);457457+ rc = eeh_reset_device(frozen_edev, NULL);486458 if (rc) {487459 printk(KERN_WARNING "EEH: Cannot reset, rc=%d\n", rc);488460 goto hard_fail;···501473 /* Tell all device drivers that they can resume operations */502474 pci_walk_bus(frozen_bus, eeh_report_resume, NULL);503475504504- return frozen_pdn;476476+ return frozen_edev;505477506478excess_failures:507479 /*···514486 "has failed %d times in the last hour "515487 "and has been permanently disabled.\n"516488 "Please try reseating this device or replacing it.\n",517517- location, drv_str, pci_str, frozen_pdn->eeh_freeze_count);489489+ location, drv_str, pci_str, frozen_edev->freeze_count);518490 goto perm_error;519491520492hard_fail:···525497 location, drv_str, pci_str);526498527499perm_error:528528- eeh_slot_error_detail(frozen_pdn, EEH_LOG_PERM_FAILURE);500500+ eeh_slot_error_detail(frozen_edev, EEH_LOG_PERM);529501530502 /* Notify all devices that they're about to go down. */531503 pci_walk_bus(frozen_bus, eeh_report_failure, NULL);···536508 return NULL;537509}538510539539-/* ---------- end of file ---------- */
+28-27
arch/powerpc/platforms/pseries/eeh_event.c
···11/*22- * eeh_event.c33- *42 * This program is free software; you can redistribute it and/or modify53 * it under the terms of the GNU General Public License as published by64 * the Free Software Foundation; either version 2 of the License, or···4446DEFINE_MUTEX(eeh_event_mutex);45474648/**4747- * eeh_event_handler - dispatch EEH events.4949+ * eeh_event_handler - Dispatch EEH events.4850 * @dummy - unused4951 *5052 * The detection of a frozen slot can occur inside an interrupt,···5658static int eeh_event_handler(void * dummy)5759{5860 unsigned long flags;5959- struct eeh_event *event;6060- struct pci_dn *pdn;6161+ struct eeh_event *event;6262+ struct eeh_dev *edev;61636262- daemonize ("eehd");6464+ daemonize("eehd");6365 set_current_state(TASK_INTERRUPTIBLE);64666567 spin_lock_irqsave(&eeh_eventlist_lock, flags);···77797880 /* Serialize processing of EEH events */7981 mutex_lock(&eeh_event_mutex);8080- eeh_mark_slot(event->dn, EEH_MODE_RECOVERING);8282+ edev = event->edev;8383+ eeh_mark_slot(eeh_dev_to_of_node(edev), EEH_MODE_RECOVERING);81848285 printk(KERN_INFO "EEH: Detected PCI bus error on device %s\n",8383- eeh_pci_name(event->dev));8686+ eeh_pci_name(edev->pdev));84878585- pdn = handle_eeh_events(event);8888+ edev = handle_eeh_events(event);86898787- eeh_clear_slot(event->dn, EEH_MODE_RECOVERING);8888- pci_dev_put(event->dev);9090+ eeh_clear_slot(eeh_dev_to_of_node(edev), EEH_MODE_RECOVERING);9191+ pci_dev_put(edev->pdev);9292+8993 kfree(event);9094 mutex_unlock(&eeh_event_mutex);91959296 /* If there are no new errors after an hour, clear the counter. */9393- if (pdn && pdn->eeh_freeze_count>0) {9494- msleep_interruptible (3600*1000);9595- if (pdn->eeh_freeze_count>0)9696- pdn->eeh_freeze_count--;9797+ if (edev && edev->freeze_count>0) {9898+ msleep_interruptible(3600*1000);9999+ if (edev->freeze_count>0)100100+ edev->freeze_count--;101101+97102 }9810399104 return 0;100105}101106102107/**103103- * eeh_thread_launcher108108+ * eeh_thread_launcher - Start kernel thread to handle EEH events104109 * @dummy - unused110110+ *111111+ * This routine is called to start the kernel thread for processing112112+ * EEH event.105113 */106114static void eeh_thread_launcher(struct work_struct *dummy)107115{···116112}117113118114/**119119- * eeh_send_failure_event - generate a PCI error event120120- * @dev pci device115115+ * eeh_send_failure_event - Generate a PCI error event116116+ * @edev: EEH device121117 *122118 * This routine can be called within an interrupt context;123119 * the actual event will be delivered in a normal context124120 * (from a workqueue).125121 */126126-int eeh_send_failure_event (struct device_node *dn,127127- struct pci_dev *dev)122122+int eeh_send_failure_event(struct eeh_dev *edev)128123{129124 unsigned long flags;130125 struct eeh_event *event;126126+ struct device_node *dn = eeh_dev_to_of_node(edev);131127 const char *location;132128133129 if (!mem_init_done) {···139135 }140136 event = kmalloc(sizeof(*event), GFP_ATOMIC);141137 if (event == NULL) {142142- printk (KERN_ERR "EEH: out of memory, event not handled\n");138138+ printk(KERN_ERR "EEH: out of memory, event not handled\n");143139 return 1;144140 }145141146146- if (dev)147147- pci_dev_get(dev);142142+ if (edev->pdev)143143+ pci_dev_get(edev->pdev);148144149149- event->dn = dn;150150- event->dev = dev;145145+ event->edev = edev;151146152147 /* We may or may not be called in an interrupt context */153148 spin_lock_irqsave(&eeh_eventlist_lock, flags);···157154158155 return 0;159156}160160-161161-/********************** END OF FILE ******************************/
+565
arch/powerpc/platforms/pseries/eeh_pseries.c
···11+/*22+ * The file intends to implement the platform dependent EEH operations on pseries.33+ * Actually, the pseries platform is built based on RTAS heavily. That means the44+ * pseries platform dependent EEH operations will be built on RTAS calls. The functions55+ * are devired from arch/powerpc/platforms/pseries/eeh.c and necessary cleanup has66+ * been done.77+ *88+ * Copyright Benjamin Herrenschmidt & Gavin Shan, IBM Corporation 2011.99+ * Copyright IBM Corporation 2001, 2005, 20061010+ * Copyright Dave Engebretsen & Todd Inglett 20011111+ * Copyright Linas Vepstas 2005, 20061212+ *1313+ * This program is free software; you can redistribute it and/or modify1414+ * it under the terms of the GNU General Public License as published by1515+ * the Free Software Foundation; either version 2 of the License, or1616+ * (at your option) any later version.1717+ *1818+ * This program is distributed in the hope that it will be useful,1919+ * but WITHOUT ANY WARRANTY; without even the implied warranty of2020+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the2121+ * GNU General Public License for more details.2222+ *2323+ * You should have received a copy of the GNU General Public License2424+ * along with this program; if not, write to the Free Software2525+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA2626+ */2727+2828+#include <linux/atomic.h>2929+#include <linux/delay.h>3030+#include <linux/export.h>3131+#include <linux/init.h>3232+#include <linux/list.h>3333+#include <linux/of.h>3434+#include <linux/pci.h>3535+#include <linux/proc_fs.h>3636+#include <linux/rbtree.h>3737+#include <linux/sched.h>3838+#include <linux/seq_file.h>3939+#include <linux/spinlock.h>4040+4141+#include <asm/eeh.h>4242+#include <asm/eeh_event.h>4343+#include <asm/io.h>4444+#include <asm/machdep.h>4545+#include <asm/ppc-pci.h>4646+#include <asm/rtas.h>4747+4848+/* RTAS tokens */4949+static int ibm_set_eeh_option;5050+static int ibm_set_slot_reset;5151+static int ibm_read_slot_reset_state;5252+static int ibm_read_slot_reset_state2;5353+static int ibm_slot_error_detail;5454+static int ibm_get_config_addr_info;5555+static int ibm_get_config_addr_info2;5656+static int ibm_configure_bridge;5757+static int ibm_configure_pe;5858+5959+/*6060+ * Buffer for reporting slot-error-detail rtas calls. Its here6161+ * in BSS, and not dynamically alloced, so that it ends up in6262+ * RMO where RTAS can access it.6363+ */6464+static unsigned char slot_errbuf[RTAS_ERROR_LOG_MAX];6565+static DEFINE_SPINLOCK(slot_errbuf_lock);6666+static int eeh_error_buf_size;6767+6868+/**6969+ * pseries_eeh_init - EEH platform dependent initialization7070+ *7171+ * EEH platform dependent initialization on pseries.7272+ */7373+static int pseries_eeh_init(void)7474+{7575+ /* figure out EEH RTAS function call tokens */7676+ ibm_set_eeh_option = rtas_token("ibm,set-eeh-option");7777+ ibm_set_slot_reset = rtas_token("ibm,set-slot-reset");7878+ ibm_read_slot_reset_state2 = rtas_token("ibm,read-slot-reset-state2");7979+ ibm_read_slot_reset_state = rtas_token("ibm,read-slot-reset-state");8080+ ibm_slot_error_detail = rtas_token("ibm,slot-error-detail");8181+ ibm_get_config_addr_info2 = rtas_token("ibm,get-config-addr-info2");8282+ ibm_get_config_addr_info = rtas_token("ibm,get-config-addr-info");8383+ ibm_configure_pe = rtas_token("ibm,configure-pe");8484+ ibm_configure_bridge = rtas_token ("ibm,configure-bridge");8585+8686+ /* necessary sanity check */8787+ if (ibm_set_eeh_option == RTAS_UNKNOWN_SERVICE) {8888+ pr_warning("%s: RTAS service <ibm,set-eeh-option> invalid\n",8989+ __func__);9090+ return -EINVAL;9191+ } else if (ibm_set_slot_reset == RTAS_UNKNOWN_SERVICE) {9292+ pr_warning("%s: RTAS service <ibm, set-slot-reset> invalid\n",9393+ __func__);9494+ return -EINVAL;9595+ } else if (ibm_read_slot_reset_state2 == RTAS_UNKNOWN_SERVICE &&9696+ ibm_read_slot_reset_state == RTAS_UNKNOWN_SERVICE) {9797+ pr_warning("%s: RTAS service <ibm,read-slot-reset-state2> and "9898+ "<ibm,read-slot-reset-state> invalid\n",9999+ __func__);100100+ return -EINVAL;101101+ } else if (ibm_slot_error_detail == RTAS_UNKNOWN_SERVICE) {102102+ pr_warning("%s: RTAS service <ibm,slot-error-detail> invalid\n",103103+ __func__);104104+ return -EINVAL;105105+ } else if (ibm_get_config_addr_info2 == RTAS_UNKNOWN_SERVICE &&106106+ ibm_get_config_addr_info == RTAS_UNKNOWN_SERVICE) {107107+ pr_warning("%s: RTAS service <ibm,get-config-addr-info2> and "108108+ "<ibm,get-config-addr-info> invalid\n",109109+ __func__);110110+ return -EINVAL;111111+ } else if (ibm_configure_pe == RTAS_UNKNOWN_SERVICE &&112112+ ibm_configure_bridge == RTAS_UNKNOWN_SERVICE) {113113+ pr_warning("%s: RTAS service <ibm,configure-pe> and "114114+ "<ibm,configure-bridge> invalid\n",115115+ __func__);116116+ return -EINVAL;117117+ }118118+119119+ /* Initialize error log lock and size */120120+ spin_lock_init(&slot_errbuf_lock);121121+ eeh_error_buf_size = rtas_token("rtas-error-log-max");122122+ if (eeh_error_buf_size == RTAS_UNKNOWN_SERVICE) {123123+ pr_warning("%s: unknown EEH error log size\n",124124+ __func__);125125+ eeh_error_buf_size = 1024;126126+ } else if (eeh_error_buf_size > RTAS_ERROR_LOG_MAX) {127127+ pr_warning("%s: EEH error log size %d exceeds the maximal %d\n",128128+ __func__, eeh_error_buf_size, RTAS_ERROR_LOG_MAX);129129+ eeh_error_buf_size = RTAS_ERROR_LOG_MAX;130130+ }131131+132132+ return 0;133133+}134134+135135+/**136136+ * pseries_eeh_set_option - Initialize EEH or MMIO/DMA reenable137137+ * @dn: device node138138+ * @option: operation to be issued139139+ *140140+ * The function is used to control the EEH functionality globally.141141+ * Currently, following options are support according to PAPR:142142+ * Enable EEH, Disable EEH, Enable MMIO and Enable DMA143143+ */144144+static int pseries_eeh_set_option(struct device_node *dn, int option)145145+{146146+ int ret = 0;147147+ struct eeh_dev *edev;148148+ const u32 *reg;149149+ int config_addr;150150+151151+ edev = of_node_to_eeh_dev(dn);152152+153153+ /*154154+ * When we're enabling or disabling EEH functioality on155155+ * the particular PE, the PE config address is possibly156156+ * unavailable. Therefore, we have to figure it out from157157+ * the FDT node.158158+ */159159+ switch (option) {160160+ case EEH_OPT_DISABLE:161161+ case EEH_OPT_ENABLE:162162+ reg = of_get_property(dn, "reg", NULL);163163+ config_addr = reg[0];164164+ break;165165+166166+ case EEH_OPT_THAW_MMIO:167167+ case EEH_OPT_THAW_DMA:168168+ config_addr = edev->config_addr;169169+ if (edev->pe_config_addr)170170+ config_addr = edev->pe_config_addr;171171+ break;172172+173173+ default:174174+ pr_err("%s: Invalid option %d\n",175175+ __func__, option);176176+ return -EINVAL;177177+ }178178+179179+ ret = rtas_call(ibm_set_eeh_option, 4, 1, NULL,180180+ config_addr, BUID_HI(edev->phb->buid),181181+ BUID_LO(edev->phb->buid), option);182182+183183+ return ret;184184+}185185+186186+/**187187+ * pseries_eeh_get_pe_addr - Retrieve PE address188188+ * @dn: device node189189+ *190190+ * Retrieve the assocated PE address. Actually, there're 2 RTAS191191+ * function calls dedicated for the purpose. We need implement192192+ * it through the new function and then the old one. Besides,193193+ * you should make sure the config address is figured out from194194+ * FDT node before calling the function.195195+ *196196+ * It's notable that zero'ed return value means invalid PE config197197+ * address.198198+ */199199+static int pseries_eeh_get_pe_addr(struct device_node *dn)200200+{201201+ struct eeh_dev *edev;202202+ int ret = 0;203203+ int rets[3];204204+205205+ edev = of_node_to_eeh_dev(dn);206206+207207+ if (ibm_get_config_addr_info2 != RTAS_UNKNOWN_SERVICE) {208208+ /*209209+ * First of all, we need to make sure there has one PE210210+ * associated with the device. Otherwise, PE address is211211+ * meaningless.212212+ */213213+ ret = rtas_call(ibm_get_config_addr_info2, 4, 2, rets,214214+ edev->config_addr, BUID_HI(edev->phb->buid),215215+ BUID_LO(edev->phb->buid), 1);216216+ if (ret || (rets[0] == 0))217217+ return 0;218218+219219+ /* Retrieve the associated PE config address */220220+ ret = rtas_call(ibm_get_config_addr_info2, 4, 2, rets,221221+ edev->config_addr, BUID_HI(edev->phb->buid),222222+ BUID_LO(edev->phb->buid), 0);223223+ if (ret) {224224+ pr_warning("%s: Failed to get PE address for %s\n",225225+ __func__, dn->full_name);226226+ return 0;227227+ }228228+229229+ return rets[0];230230+ }231231+232232+ if (ibm_get_config_addr_info != RTAS_UNKNOWN_SERVICE) {233233+ ret = rtas_call(ibm_get_config_addr_info, 4, 2, rets,234234+ edev->config_addr, BUID_HI(edev->phb->buid),235235+ BUID_LO(edev->phb->buid), 0);236236+ if (ret) {237237+ pr_warning("%s: Failed to get PE address for %s\n",238238+ __func__, dn->full_name);239239+ return 0;240240+ }241241+242242+ return rets[0];243243+ }244244+245245+ return ret;246246+}247247+248248+/**249249+ * pseries_eeh_get_state - Retrieve PE state250250+ * @dn: PE associated device node251251+ * @state: return value252252+ *253253+ * Retrieve the state of the specified PE. On RTAS compliant254254+ * pseries platform, there already has one dedicated RTAS function255255+ * for the purpose. It's notable that the associated PE config address256256+ * might be ready when calling the function. Therefore, endeavour to257257+ * use the PE config address if possible. Further more, there're 2258258+ * RTAS calls for the purpose, we need to try the new one and back259259+ * to the old one if the new one couldn't work properly.260260+ */261261+static int pseries_eeh_get_state(struct device_node *dn, int *state)262262+{263263+ struct eeh_dev *edev;264264+ int config_addr;265265+ int ret;266266+ int rets[4];267267+ int result;268268+269269+ /* Figure out PE config address if possible */270270+ edev = of_node_to_eeh_dev(dn);271271+ config_addr = edev->config_addr;272272+ if (edev->pe_config_addr)273273+ config_addr = edev->pe_config_addr;274274+275275+ if (ibm_read_slot_reset_state2 != RTAS_UNKNOWN_SERVICE) {276276+ ret = rtas_call(ibm_read_slot_reset_state2, 3, 4, rets,277277+ config_addr, BUID_HI(edev->phb->buid),278278+ BUID_LO(edev->phb->buid));279279+ } else if (ibm_read_slot_reset_state != RTAS_UNKNOWN_SERVICE) {280280+ /* Fake PE unavailable info */281281+ rets[2] = 0;282282+ ret = rtas_call(ibm_read_slot_reset_state, 3, 3, rets,283283+ config_addr, BUID_HI(edev->phb->buid),284284+ BUID_LO(edev->phb->buid));285285+ } else {286286+ return EEH_STATE_NOT_SUPPORT;287287+ }288288+289289+ if (ret)290290+ return ret;291291+292292+ /* Parse the result out */293293+ result = 0;294294+ if (rets[1]) {295295+ switch(rets[0]) {296296+ case 0:297297+ result &= ~EEH_STATE_RESET_ACTIVE;298298+ result |= EEH_STATE_MMIO_ACTIVE;299299+ result |= EEH_STATE_DMA_ACTIVE;300300+ break;301301+ case 1:302302+ result |= EEH_STATE_RESET_ACTIVE;303303+ result |= EEH_STATE_MMIO_ACTIVE;304304+ result |= EEH_STATE_DMA_ACTIVE;305305+ break;306306+ case 2:307307+ result &= ~EEH_STATE_RESET_ACTIVE;308308+ result &= ~EEH_STATE_MMIO_ACTIVE;309309+ result &= ~EEH_STATE_DMA_ACTIVE;310310+ break;311311+ case 4:312312+ result &= ~EEH_STATE_RESET_ACTIVE;313313+ result &= ~EEH_STATE_MMIO_ACTIVE;314314+ result &= ~EEH_STATE_DMA_ACTIVE;315315+ result |= EEH_STATE_MMIO_ENABLED;316316+ break;317317+ case 5:318318+ if (rets[2]) {319319+ if (state) *state = rets[2];320320+ result = EEH_STATE_UNAVAILABLE;321321+ } else {322322+ result = EEH_STATE_NOT_SUPPORT;323323+ }324324+ default:325325+ result = EEH_STATE_NOT_SUPPORT;326326+ }327327+ } else {328328+ result = EEH_STATE_NOT_SUPPORT;329329+ }330330+331331+ return result;332332+}333333+334334+/**335335+ * pseries_eeh_reset - Reset the specified PE336336+ * @dn: PE associated device node337337+ * @option: reset option338338+ *339339+ * Reset the specified PE340340+ */341341+static int pseries_eeh_reset(struct device_node *dn, int option)342342+{343343+ struct eeh_dev *edev;344344+ int config_addr;345345+ int ret;346346+347347+ /* Figure out PE address */348348+ edev = of_node_to_eeh_dev(dn);349349+ config_addr = edev->config_addr;350350+ if (edev->pe_config_addr)351351+ config_addr = edev->pe_config_addr;352352+353353+ /* Reset PE through RTAS call */354354+ ret = rtas_call(ibm_set_slot_reset, 4, 1, NULL,355355+ config_addr, BUID_HI(edev->phb->buid),356356+ BUID_LO(edev->phb->buid), option);357357+358358+ /* If fundamental-reset not supported, try hot-reset */359359+ if (option == EEH_RESET_FUNDAMENTAL &&360360+ ret == -8) {361361+ ret = rtas_call(ibm_set_slot_reset, 4, 1, NULL,362362+ config_addr, BUID_HI(edev->phb->buid),363363+ BUID_LO(edev->phb->buid), EEH_RESET_HOT);364364+ }365365+366366+ return ret;367367+}368368+369369+/**370370+ * pseries_eeh_wait_state - Wait for PE state371371+ * @dn: PE associated device node372372+ * @max_wait: maximal period in microsecond373373+ *374374+ * Wait for the state of associated PE. It might take some time375375+ * to retrieve the PE's state.376376+ */377377+static int pseries_eeh_wait_state(struct device_node *dn, int max_wait)378378+{379379+ int ret;380380+ int mwait;381381+382382+ /*383383+ * According to PAPR, the state of PE might be temporarily384384+ * unavailable. Under the circumstance, we have to wait385385+ * for indicated time determined by firmware. The maximal386386+ * wait time is 5 minutes, which is acquired from the original387387+ * EEH implementation. Also, the original implementation388388+ * also defined the minimal wait time as 1 second.389389+ */390390+#define EEH_STATE_MIN_WAIT_TIME (1000)391391+#define EEH_STATE_MAX_WAIT_TIME (300 * 1000)392392+393393+ while (1) {394394+ ret = pseries_eeh_get_state(dn, &mwait);395395+396396+ /*397397+ * If the PE's state is temporarily unavailable,398398+ * we have to wait for the specified time. Otherwise,399399+ * the PE's state will be returned immediately.400400+ */401401+ if (ret != EEH_STATE_UNAVAILABLE)402402+ return ret;403403+404404+ if (max_wait <= 0) {405405+ pr_warning("%s: Timeout when getting PE's state (%d)\n",406406+ __func__, max_wait);407407+ return EEH_STATE_NOT_SUPPORT;408408+ }409409+410410+ if (mwait <= 0) {411411+ pr_warning("%s: Firmware returned bad wait value %d\n",412412+ __func__, mwait);413413+ mwait = EEH_STATE_MIN_WAIT_TIME;414414+ } else if (mwait > EEH_STATE_MAX_WAIT_TIME) {415415+ pr_warning("%s: Firmware returned too long wait value %d\n",416416+ __func__, mwait);417417+ mwait = EEH_STATE_MAX_WAIT_TIME;418418+ }419419+420420+ max_wait -= mwait;421421+ msleep(mwait);422422+ }423423+424424+ return EEH_STATE_NOT_SUPPORT;425425+}426426+427427+/**428428+ * pseries_eeh_get_log - Retrieve error log429429+ * @dn: device node430430+ * @severity: temporary or permanent error log431431+ * @drv_log: driver log to be combined with retrieved error log432432+ * @len: length of driver log433433+ *434434+ * Retrieve the temporary or permanent error from the PE.435435+ * Actually, the error will be retrieved through the dedicated436436+ * RTAS call.437437+ */438438+static int pseries_eeh_get_log(struct device_node *dn, int severity, char *drv_log, unsigned long len)439439+{440440+ struct eeh_dev *edev;441441+ int config_addr;442442+ unsigned long flags;443443+ int ret;444444+445445+ edev = of_node_to_eeh_dev(dn);446446+ spin_lock_irqsave(&slot_errbuf_lock, flags);447447+ memset(slot_errbuf, 0, eeh_error_buf_size);448448+449449+ /* Figure out the PE address */450450+ config_addr = edev->config_addr;451451+ if (edev->pe_config_addr)452452+ config_addr = edev->pe_config_addr;453453+454454+ ret = rtas_call(ibm_slot_error_detail, 8, 1, NULL, config_addr,455455+ BUID_HI(edev->phb->buid), BUID_LO(edev->phb->buid),456456+ virt_to_phys(drv_log), len,457457+ virt_to_phys(slot_errbuf), eeh_error_buf_size,458458+ severity);459459+ if (!ret)460460+ log_error(slot_errbuf, ERR_TYPE_RTAS_LOG, 0);461461+ spin_unlock_irqrestore(&slot_errbuf_lock, flags);462462+463463+ return ret;464464+}465465+466466+/**467467+ * pseries_eeh_configure_bridge - Configure PCI bridges in the indicated PE468468+ * @dn: PE associated device node469469+ *470470+ * The function will be called to reconfigure the bridges included471471+ * in the specified PE so that the mulfunctional PE would be recovered472472+ * again.473473+ */474474+static int pseries_eeh_configure_bridge(struct device_node *dn)475475+{476476+ struct eeh_dev *edev;477477+ int config_addr;478478+ int ret;479479+480480+ /* Figure out the PE address */481481+ edev = of_node_to_eeh_dev(dn);482482+ config_addr = edev->config_addr;483483+ if (edev->pe_config_addr)484484+ config_addr = edev->pe_config_addr;485485+486486+ /* Use new configure-pe function, if supported */487487+ if (ibm_configure_pe != RTAS_UNKNOWN_SERVICE) {488488+ ret = rtas_call(ibm_configure_pe, 3, 1, NULL,489489+ config_addr, BUID_HI(edev->phb->buid),490490+ BUID_LO(edev->phb->buid));491491+ } else if (ibm_configure_bridge != RTAS_UNKNOWN_SERVICE) {492492+ ret = rtas_call(ibm_configure_bridge, 3, 1, NULL,493493+ config_addr, BUID_HI(edev->phb->buid),494494+ BUID_LO(edev->phb->buid));495495+ } else {496496+ return -EFAULT;497497+ }498498+499499+ if (ret)500500+ pr_warning("%s: Unable to configure bridge %d for %s\n",501501+ __func__, ret, dn->full_name);502502+503503+ return ret;504504+}505505+506506+/**507507+ * pseries_eeh_read_config - Read PCI config space508508+ * @dn: device node509509+ * @where: PCI address510510+ * @size: size to read511511+ * @val: return value512512+ *513513+ * Read config space from the speicifed device514514+ */515515+static int pseries_eeh_read_config(struct device_node *dn, int where, int size, u32 *val)516516+{517517+ struct pci_dn *pdn;518518+519519+ pdn = PCI_DN(dn);520520+521521+ return rtas_read_config(pdn, where, size, val);522522+}523523+524524+/**525525+ * pseries_eeh_write_config - Write PCI config space526526+ * @dn: device node527527+ * @where: PCI address528528+ * @size: size to write529529+ * @val: value to be written530530+ *531531+ * Write config space to the specified device532532+ */533533+static int pseries_eeh_write_config(struct device_node *dn, int where, int size, u32 val)534534+{535535+ struct pci_dn *pdn;536536+537537+ pdn = PCI_DN(dn);538538+539539+ return rtas_write_config(pdn, where, size, val);540540+}541541+542542+static struct eeh_ops pseries_eeh_ops = {543543+ .name = "pseries",544544+ .init = pseries_eeh_init,545545+ .set_option = pseries_eeh_set_option,546546+ .get_pe_addr = pseries_eeh_get_pe_addr,547547+ .get_state = pseries_eeh_get_state,548548+ .reset = pseries_eeh_reset,549549+ .wait_state = pseries_eeh_wait_state,550550+ .get_log = pseries_eeh_get_log,551551+ .configure_bridge = pseries_eeh_configure_bridge,552552+ .read_config = pseries_eeh_read_config,553553+ .write_config = pseries_eeh_write_config554554+};555555+556556+/**557557+ * eeh_pseries_init - Register platform dependent EEH operations558558+ *559559+ * EEH initialization on pseries platform. This function should be560560+ * called before any EEH related functions.561561+ */562562+int __init eeh_pseries_init(void)563563+{564564+ return eeh_ops_register(&pseries_eeh_ops);565565+}
···147147148148 pci_devs_phb_init_dynamic(phb);149149150150+ /* Create EEH devices for the PHB */151151+ eeh_dev_phb_init_dynamic(phb);152152+150153 if (dn->child)151154 eeh_add_device_tree_early(dn);152155
+6-1
arch/powerpc/platforms/pseries/setup.c
···260260 switch (action) {261261 case PSERIES_RECONFIG_ADD:262262 pci = np->parent->data;263263- if (pci)263263+ if (pci) {264264 update_dn_pci_info(np, pci->phb);265265+266266+ /* Create EEH device for the OF node */267267+ eeh_dev_init(np, pci->phb);268268+ }265269 break;266270 default:267271 err = NOTIFY_DONE;···385381386382 /* Find and initialize PCI host bridges */387383 init_pci_config_tokens();384384+ eeh_pseries_init();388385 find_and_init_phbs();389386 pSeries_reconfig_notifier_register(&pci_dn_reconfig_nb);390387 eeh_init();
+10
include/linux/of.h
···5858 struct kref kref;5959 unsigned long _flags;6060 void *data;6161+#if defined(CONFIG_EEH)6262+ struct eeh_dev *edev;6363+#endif6164#if defined(CONFIG_SPARC)6265 char *path_component_name;6366 unsigned int unique_id;···7471 int args_count;7572 uint32_t args[MAX_PHANDLE_ARGS];7673};7474+7575+#if defined(CONFIG_EEH)7676+static inline struct eeh_dev *of_node_to_eeh_dev(struct device_node *dn)7777+{7878+ return dn->edev;7979+}8080+#endif77817882#if defined(CONFIG_SPARC) || !defined(CONFIG_OF)7983/* Dummy ref counting routines - to be implemented later */