aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/misc/sgi-xp/xp_main.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/misc/sgi-xp/xp_main.c')
-rw-r--r--drivers/misc/sgi-xp/xp_main.c84
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 */
30EXPORT_SYMBOL_GPL(xp_nofault_PIOR);
31 23
32u64 xp_nofault_PIOR_target; 24struct device_driver xp_dbg_name = {
33EXPORT_SYMBOL_GPL(xp_nofault_PIOR_target); 25 .name = "xp"
26};
27
28struct device xp_dbg_subname = {
29 .bus_id = {0}, /* set to "" */
30 .driver = &xp_dbg_name
31};
32
33struct device *xp = &xp_dbg_subname;
34
35/* max #of partitions possible */
36short xp_max_npartitions;
37EXPORT_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 */
39struct xpc_registration xpc_registrations[XPC_NCHANNELS]; 43struct xpc_registration xpc_registrations[XPC_MAX_NCHANNELS];
40EXPORT_SYMBOL_GPL(xpc_registrations); 44EXPORT_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);
221int __init 225int __init
222xp_init(void) 226xp_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);
264void __exit 250void __exit
265xp_exit(void) 251xp_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
275module_exit(xp_exit); 259module_exit(xp_exit);