aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/platforms/pseries
diff options
context:
space:
mode:
authorGavin Shan <shangw@linux.vnet.ibm.com>2012-02-27 15:03:53 -0500
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2012-03-08 19:08:54 -0500
commitaa1e6374ae11788752535ae0c8c6395c9cad1393 (patch)
tree6763bddf1be60f6753badbfc00459e93c4625be7 /arch/powerpc/platforms/pseries
parentcce4b2d243ddd9e8d5da159b893117afd7ccad5c (diff)
powerpc/eeh: Platform dependent EEH operations
EEH has been implemented on RTAS-compliant pSeries platform. That's to say, the EEH operations will be implemented through RTAS calls eventually. The situation limited feasible extension on EEH. In order to support EEH on multiple platforms like pseries and powernv simutaneously. We have to split the platform dependent EEH options up out of current implementation. The patch addresses supporting EEH on multiple platforms. The pseries platform dependent EEH operations will be abstracted by struct eeh_ops. EEH core components will be built based on the registered EEH operations. With the mechanism, what the individual platform needs to do is implement platform dependent EEH operations. For now, the pseries platform is covered under the mechanism. That means we have to think about other platforms to support EEH, like powernv. Besides, we only have framework for the mechanism and we have to implement it for pseries platform later. Signed-off-by: Gavin Shan <shangw@linux.vnet.ibm.com> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Diffstat (limited to 'arch/powerpc/platforms/pseries')
-rw-r--r--arch/powerpc/platforms/pseries/Makefile2
-rw-r--r--arch/powerpc/platforms/pseries/eeh.c53
-rw-r--r--arch/powerpc/platforms/pseries/eeh_pseries.c183
-rw-r--r--arch/powerpc/platforms/pseries/setup.c1
4 files changed, 238 insertions, 1 deletions
diff --git a/arch/powerpc/platforms/pseries/Makefile b/arch/powerpc/platforms/pseries/Makefile
index 67b3e6e0cf3f..ee873cf4fe46 100644
--- a/arch/powerpc/platforms/pseries/Makefile
+++ b/arch/powerpc/platforms/pseries/Makefile
@@ -6,7 +6,7 @@ obj-y := lpar.o hvCall.o nvram.o reconfig.o \
6 firmware.o power.o dlpar.o mobility.o 6 firmware.o power.o dlpar.o mobility.o
7obj-$(CONFIG_SMP) += smp.o 7obj-$(CONFIG_SMP) += smp.o
8obj-$(CONFIG_SCANLOG) += scanlog.o 8obj-$(CONFIG_SCANLOG) += scanlog.o
9obj-$(CONFIG_EEH) += eeh.o eeh_cache.o eeh_driver.o eeh_event.o eeh_sysfs.o 9obj-$(CONFIG_EEH) += eeh.o eeh_cache.o eeh_driver.o eeh_event.o eeh_sysfs.o eeh_pseries.o
10obj-$(CONFIG_KEXEC) += kexec.o 10obj-$(CONFIG_KEXEC) += kexec.o
11obj-$(CONFIG_PCI) += pci.o pci_dlpar.o 11obj-$(CONFIG_PCI) += pci.o pci_dlpar.o
12obj-$(CONFIG_PSERIES_MSI) += msi.o 12obj-$(CONFIG_PSERIES_MSI) += msi.o
diff --git a/arch/powerpc/platforms/pseries/eeh.c b/arch/powerpc/platforms/pseries/eeh.c
index fa885891e1c3..b0e3fb0b32a5 100644
--- a/arch/powerpc/platforms/pseries/eeh.c
+++ b/arch/powerpc/platforms/pseries/eeh.c
@@ -97,6 +97,9 @@ static int ibm_get_config_addr_info2;
97static int ibm_configure_bridge; 97static int ibm_configure_bridge;
98static int ibm_configure_pe; 98static int ibm_configure_pe;
99 99
100/* Platform dependent EEH operations */
101struct eeh_ops *eeh_ops = NULL;
102
100int eeh_subsystem_enabled; 103int eeh_subsystem_enabled;
101EXPORT_SYMBOL(eeh_subsystem_enabled); 104EXPORT_SYMBOL(eeh_subsystem_enabled);
102 105
@@ -1208,6 +1211,56 @@ static void *eeh_early_enable(struct device_node *dn, void *data)
1208} 1211}
1209 1212
1210/** 1213/**
1214 * eeh_ops_register - Register platform dependent EEH operations
1215 * @ops: platform dependent EEH operations
1216 *
1217 * Register the platform dependent EEH operation callback
1218 * functions. The platform should call this function before
1219 * any other EEH operations.
1220 */
1221int __init eeh_ops_register(struct eeh_ops *ops)
1222{
1223 if (!ops->name) {
1224 pr_warning("%s: Invalid EEH ops name for %p\n",
1225 __func__, ops);
1226 return -EINVAL;
1227 }
1228
1229 if (eeh_ops && eeh_ops != ops) {
1230 pr_warning("%s: EEH ops of platform %s already existing (%s)\n",
1231 __func__, eeh_ops->name, ops->name);
1232 return -EEXIST;
1233 }
1234
1235 eeh_ops = ops;
1236
1237 return 0;
1238}
1239
1240/**
1241 * eeh_ops_unregister - Unreigster platform dependent EEH operations
1242 * @name: name of EEH platform operations
1243 *
1244 * Unregister the platform dependent EEH operation callback
1245 * functions.
1246 */
1247int __exit eeh_ops_unregister(const char *name)
1248{
1249 if (!name || !strlen(name)) {
1250 pr_warning("%s: Invalid EEH ops name\n",
1251 __func__);
1252 return -EINVAL;
1253 }
1254
1255 if (eeh_ops && !strcmp(eeh_ops->name, name)) {
1256 eeh_ops = NULL;
1257 return 0;
1258 }
1259
1260 return -EEXIST;
1261}
1262
1263/**
1211 * eeh_init - EEH initialization 1264 * eeh_init - EEH initialization
1212 * 1265 *
1213 * Initialize EEH by trying to enable it for all of the adapters in the system. 1266 * Initialize EEH by trying to enable it for all of the adapters in the system.
diff --git a/arch/powerpc/platforms/pseries/eeh_pseries.c b/arch/powerpc/platforms/pseries/eeh_pseries.c
new file mode 100644
index 000000000000..61a9050ba969
--- /dev/null
+++ b/arch/powerpc/platforms/pseries/eeh_pseries.c
@@ -0,0 +1,183 @@
1/*
2 * The file intends to implement the platform dependent EEH operations on pseries.
3 * Actually, the pseries platform is built based on RTAS heavily. That means the
4 * pseries platform dependent EEH operations will be built on RTAS calls. The functions
5 * are devired from arch/powerpc/platforms/pseries/eeh.c and necessary cleanup has
6 * been done.
7 *
8 * Copyright Benjamin Herrenschmidt & Gavin Shan, IBM Corporation 2011.
9 * Copyright IBM Corporation 2001, 2005, 2006
10 * Copyright Dave Engebretsen & Todd Inglett 2001
11 * Copyright Linas Vepstas 2005, 2006
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
17 *
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 */
27
28#include <linux/atomic.h>
29#include <linux/delay.h>
30#include <linux/export.h>
31#include <linux/init.h>
32#include <linux/list.h>
33#include <linux/of.h>
34#include <linux/pci.h>
35#include <linux/proc_fs.h>
36#include <linux/rbtree.h>
37#include <linux/sched.h>
38#include <linux/seq_file.h>
39#include <linux/spinlock.h>
40
41#include <asm/eeh.h>
42#include <asm/eeh_event.h>
43#include <asm/io.h>
44#include <asm/machdep.h>
45#include <asm/ppc-pci.h>
46#include <asm/rtas.h>
47
48/**
49 * pseries_eeh_init - EEH platform dependent initialization
50 *
51 * EEH platform dependent initialization on pseries.
52 */
53static int pseries_eeh_init(void)
54{
55 return 0;
56}
57
58/**
59 * pseries_eeh_set_option - Initialize EEH or MMIO/DMA reenable
60 * @dn: device node
61 * @option: operation to be issued
62 *
63 * The function is used to control the EEH functionality globally.
64 * Currently, following options are support according to PAPR:
65 * Enable EEH, Disable EEH, Enable MMIO and Enable DMA
66 */
67static int pseries_eeh_set_option(struct device_node *dn, int option)
68{
69 return 0;
70}
71
72/**
73 * pseries_eeh_get_pe_addr - Retrieve PE address
74 * @dn: device node
75 *
76 * Retrieve the assocated PE address. Actually, there're 2 RTAS
77 * function calls dedicated for the purpose. We need implement
78 * it through the new function and then the old one. Besides,
79 * you should make sure the config address is figured out from
80 * FDT node before calling the function.
81 *
82 * It's notable that zero'ed return value means invalid PE config
83 * address.
84 */
85static int pseries_eeh_get_pe_addr(struct device_node *dn)
86{
87 return 0;
88}
89
90/**
91 * pseries_eeh_get_state - Retrieve PE state
92 * @dn: PE associated device node
93 * @state: return value
94 *
95 * Retrieve the state of the specified PE. On RTAS compliant
96 * pseries platform, there already has one dedicated RTAS function
97 * for the purpose. It's notable that the associated PE config address
98 * might be ready when calling the function. Therefore, endeavour to
99 * use the PE config address if possible. Further more, there're 2
100 * RTAS calls for the purpose, we need to try the new one and back
101 * to the old one if the new one couldn't work properly.
102 */
103static int pseries_eeh_get_state(struct device_node *dn, int *state)
104{
105 return 0;
106}
107
108/**
109 * pseries_eeh_reset - Reset the specified PE
110 * @dn: PE associated device node
111 * @option: reset option
112 *
113 * Reset the specified PE
114 */
115static int pseries_eeh_reset(struct device_node *dn, int option)
116{
117 return 0;
118}
119
120/**
121 * pseries_eeh_wait_state - Wait for PE state
122 * @dn: PE associated device node
123 * @max_wait: maximal period in microsecond
124 *
125 * Wait for the state of associated PE. It might take some time
126 * to retrieve the PE's state.
127 */
128static int pseries_eeh_wait_state(struct device_node *dn, int max_wait)
129{
130 return 0;
131}
132
133/**
134 * pseries_eeh_get_log - Retrieve error log
135 * @dn: device node
136 * @severity: temporary or permanent error log
137 * @drv_log: driver log to be combined with retrieved error log
138 * @len: length of driver log
139 *
140 * Retrieve the temporary or permanent error from the PE.
141 * Actually, the error will be retrieved through the dedicated
142 * RTAS call.
143 */
144static int pseries_eeh_get_log(struct device_node *dn, int severity, char *drv_log, unsigned long len)
145{
146 return 0;
147}
148
149/**
150 * pseries_eeh_configure_bridge - Configure PCI bridges in the indicated PE
151 * @dn: PE associated device node
152 *
153 * The function will be called to reconfigure the bridges included
154 * in the specified PE so that the mulfunctional PE would be recovered
155 * again.
156 */
157static int pseries_eeh_configure_bridge(struct device_node *dn)
158{
159 return 0;
160}
161
162static struct eeh_ops pseries_eeh_ops = {
163 .name = "pseries",
164 .init = pseries_eeh_init,
165 .set_option = pseries_eeh_set_option,
166 .get_pe_addr = pseries_eeh_get_pe_addr,
167 .get_state = pseries_eeh_get_state,
168 .reset = pseries_eeh_reset,
169 .wait_state = pseries_eeh_wait_state,
170 .get_log = pseries_eeh_get_log,
171 .configure_bridge = pseries_eeh_configure_bridge
172};
173
174/**
175 * eeh_pseries_init - Register platform dependent EEH operations
176 *
177 * EEH initialization on pseries platform. This function should be
178 * called before any EEH related functions.
179 */
180int __init eeh_pseries_init(void)
181{
182 return eeh_ops_register(&pseries_eeh_ops);
183}
diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c
index d928412cfb32..62b827626ca6 100644
--- a/arch/powerpc/platforms/pseries/setup.c
+++ b/arch/powerpc/platforms/pseries/setup.c
@@ -381,6 +381,7 @@ static void __init pSeries_setup_arch(void)
381 381
382 /* Find and initialize PCI host bridges */ 382 /* Find and initialize PCI host bridges */
383 init_pci_config_tokens(); 383 init_pci_config_tokens();
384 eeh_pseries_init();
384 find_and_init_phbs(); 385 find_and_init_phbs();
385 pSeries_reconfig_notifier_register(&pci_dn_reconfig_nb); 386 pSeries_reconfig_notifier_register(&pci_dn_reconfig_nb);
386 eeh_init(); 387 eeh_init();