diff options
Diffstat (limited to 'drivers/misc/sgi-xp/xp_main.c')
-rw-r--r-- | drivers/misc/sgi-xp/xp_main.c | 84 |
1 files changed, 34 insertions, 50 deletions
diff --git a/drivers/misc/sgi-xp/xp_main.c b/drivers/misc/sgi-xp/xp_main.c index 196480b691a1..c5cec606377d 100644 --- a/drivers/misc/sgi-xp/xp_main.c +++ b/drivers/misc/sgi-xp/xp_main.c | |||
@@ -15,28 +15,32 @@ | |||
15 | */ | 15 | */ |
16 | 16 | ||
17 | #include <linux/kernel.h> | 17 | #include <linux/kernel.h> |
18 | #include <linux/interrupt.h> | ||
19 | #include <linux/module.h> | 18 | #include <linux/module.h> |
20 | #include <linux/mutex.h> | 19 | #include <linux/device.h> |
21 | #include <asm/sn/intr.h> | ||
22 | #include <asm/sn/sn_sal.h> | ||
23 | #include "xp.h" | 20 | #include "xp.h" |
24 | 21 | ||
25 | /* | 22 | /* define the XP debug device structures to be used with dev_dbg() et al */ |
26 | * The export of xp_nofault_PIOR needs to happen here since it is defined | ||
27 | * in drivers/misc/sgi-xp/xp_nofault.S. The target of the nofault read is | ||
28 | * defined here. | ||
29 | */ | ||
30 | EXPORT_SYMBOL_GPL(xp_nofault_PIOR); | ||
31 | 23 | ||
32 | u64 xp_nofault_PIOR_target; | 24 | struct device_driver xp_dbg_name = { |
33 | EXPORT_SYMBOL_GPL(xp_nofault_PIOR_target); | 25 | .name = "xp" |
26 | }; | ||
27 | |||
28 | struct device xp_dbg_subname = { | ||
29 | .bus_id = {0}, /* set to "" */ | ||
30 | .driver = &xp_dbg_name | ||
31 | }; | ||
32 | |||
33 | struct device *xp = &xp_dbg_subname; | ||
34 | |||
35 | /* max #of partitions possible */ | ||
36 | short xp_max_npartitions; | ||
37 | EXPORT_SYMBOL_GPL(xp_max_npartitions); | ||
34 | 38 | ||
35 | /* | 39 | /* |
36 | * xpc_registrations[] keeps track of xpc_connect()'s done by the kernel-level | 40 | * xpc_registrations[] keeps track of xpc_connect()'s done by the kernel-level |
37 | * users of XPC. | 41 | * users of XPC. |
38 | */ | 42 | */ |
39 | struct xpc_registration xpc_registrations[XPC_NCHANNELS]; | 43 | struct xpc_registration xpc_registrations[XPC_MAX_NCHANNELS]; |
40 | EXPORT_SYMBOL_GPL(xpc_registrations); | 44 | EXPORT_SYMBOL_GPL(xpc_registrations); |
41 | 45 | ||
42 | /* | 46 | /* |
@@ -135,7 +139,7 @@ xpc_connect(int ch_number, xpc_channel_func func, void *key, u16 payload_size, | |||
135 | { | 139 | { |
136 | struct xpc_registration *registration; | 140 | struct xpc_registration *registration; |
137 | 141 | ||
138 | DBUG_ON(ch_number < 0 || ch_number >= XPC_NCHANNELS); | 142 | DBUG_ON(ch_number < 0 || ch_number >= XPC_MAX_NCHANNELS); |
139 | DBUG_ON(payload_size == 0 || nentries == 0); | 143 | DBUG_ON(payload_size == 0 || nentries == 0); |
140 | DBUG_ON(func == NULL); | 144 | DBUG_ON(func == NULL); |
141 | DBUG_ON(assigned_limit == 0 || idle_limit > assigned_limit); | 145 | DBUG_ON(assigned_limit == 0 || idle_limit > assigned_limit); |
@@ -185,7 +189,7 @@ xpc_disconnect(int ch_number) | |||
185 | { | 189 | { |
186 | struct xpc_registration *registration; | 190 | struct xpc_registration *registration; |
187 | 191 | ||
188 | DBUG_ON(ch_number < 0 || ch_number >= XPC_NCHANNELS); | 192 | DBUG_ON(ch_number < 0 || ch_number >= XPC_MAX_NCHANNELS); |
189 | 193 | ||
190 | registration = &xpc_registrations[ch_number]; | 194 | registration = &xpc_registrations[ch_number]; |
191 | 195 | ||
@@ -221,39 +225,21 @@ EXPORT_SYMBOL_GPL(xpc_disconnect); | |||
221 | int __init | 225 | int __init |
222 | xp_init(void) | 226 | xp_init(void) |
223 | { | 227 | { |
224 | int ret, ch_number; | 228 | enum xp_retval ret; |
225 | u64 func_addr = *(u64 *)xp_nofault_PIOR; | 229 | int ch_number; |
226 | u64 err_func_addr = *(u64 *)xp_error_PIOR; | ||
227 | |||
228 | if (!ia64_platform_is("sn2")) | ||
229 | return -ENODEV; | ||
230 | 230 | ||
231 | /* | 231 | if (is_shub()) |
232 | * Register a nofault code region which performs a cross-partition | 232 | ret = xp_init_sn2(); |
233 | * PIO read. If the PIO read times out, the MCA handler will consume | 233 | else if (is_uv()) |
234 | * the error and return to a kernel-provided instruction to indicate | 234 | ret = xp_init_uv(); |
235 | * an error. This PIO read exists because it is guaranteed to timeout | ||
236 | * if the destination is down (AMO operations do not timeout on at | ||
237 | * least some CPUs on Shubs <= v1.2, which unfortunately we have to | ||
238 | * work around). | ||
239 | */ | ||
240 | ret = sn_register_nofault_code(func_addr, err_func_addr, err_func_addr, | ||
241 | 1, 1); | ||
242 | if (ret != 0) { | ||
243 | printk(KERN_ERR "XP: can't register nofault code, error=%d\n", | ||
244 | ret); | ||
245 | } | ||
246 | /* | ||
247 | * Setup the nofault PIO read target. (There is no special reason why | ||
248 | * SH_IPI_ACCESS was selected.) | ||
249 | */ | ||
250 | if (is_shub2()) | ||
251 | xp_nofault_PIOR_target = SH2_IPI_ACCESS0; | ||
252 | else | 235 | else |
253 | xp_nofault_PIOR_target = SH1_IPI_ACCESS; | 236 | ret = xpUnsupported; |
237 | |||
238 | if (ret != xpSuccess) | ||
239 | return -ENODEV; | ||
254 | 240 | ||
255 | /* initialize the connection registration mutex */ | 241 | /* initialize the connection registration mutex */ |
256 | for (ch_number = 0; ch_number < XPC_NCHANNELS; ch_number++) | 242 | for (ch_number = 0; ch_number < XPC_MAX_NCHANNELS; ch_number++) |
257 | mutex_init(&xpc_registrations[ch_number].mutex); | 243 | mutex_init(&xpc_registrations[ch_number].mutex); |
258 | 244 | ||
259 | return 0; | 245 | return 0; |
@@ -264,12 +250,10 @@ module_init(xp_init); | |||
264 | void __exit | 250 | void __exit |
265 | xp_exit(void) | 251 | xp_exit(void) |
266 | { | 252 | { |
267 | u64 func_addr = *(u64 *)xp_nofault_PIOR; | 253 | if (is_shub()) |
268 | u64 err_func_addr = *(u64 *)xp_error_PIOR; | 254 | xp_exit_sn2(); |
269 | 255 | else if (is_uv()) | |
270 | /* unregister the PIO read nofault code region */ | 256 | xp_exit_uv(); |
271 | (void)sn_register_nofault_code(func_addr, err_func_addr, | ||
272 | err_func_addr, 1, 0); | ||
273 | } | 257 | } |
274 | 258 | ||
275 | module_exit(xp_exit); | 259 | module_exit(xp_exit); |