sgi-xp: support runtime selection of xp_max_npartitions
[linux-2.6.git] / drivers / misc / sgi-xp / xp_sn2.c
1 /*
2  * This file is subject to the terms and conditions of the GNU General Public
3  * License.  See the file "COPYING" in the main directory of this archive
4  * for more details.
5  *
6  * Copyright (c) 2008 Silicon Graphics, Inc.  All Rights Reserved.
7  */
8
9 /*
10  * Cross Partition (XP) sn2-based functions.
11  *
12  *      Architecture specific implementation of common functions.
13  */
14
15 #include <linux/device.h>
16 #include <asm/sn/sn_sal.h>
17 #include "xp.h"
18
19 /*
20  * The export of xp_nofault_PIOR needs to happen here since it is defined
21  * in drivers/misc/sgi-xp/xp_nofault.S. The target of the nofault read is
22  * defined here.
23  */
24 EXPORT_SYMBOL_GPL(xp_nofault_PIOR);
25
26 u64 xp_nofault_PIOR_target;
27 EXPORT_SYMBOL_GPL(xp_nofault_PIOR_target);
28
29 /*
30  * Register a nofault code region which performs a cross-partition PIO read.
31  * If the PIO read times out, the MCA handler will consume the error and
32  * return to a kernel-provided instruction to indicate an error. This PIO read
33  * exists because it is guaranteed to timeout if the destination is down
34  * (AMO operations do not timeout on at least some CPUs on Shubs <= v1.2,
35  * which unfortunately we have to work around).
36  */
37 static enum xp_retval
38 xp_register_nofault_code_sn2(void)
39 {
40         int ret;
41         u64 func_addr;
42         u64 err_func_addr;
43
44         func_addr = *(u64 *)xp_nofault_PIOR;
45         err_func_addr = *(u64 *)xp_error_PIOR;
46         ret = sn_register_nofault_code(func_addr, err_func_addr, err_func_addr,
47                                        1, 1);
48         if (ret != 0) {
49                 dev_err(xp, "can't register nofault code, error=%d\n", ret);
50                 return xpSalError;
51         }
52         /*
53          * Setup the nofault PIO read target. (There is no special reason why
54          * SH_IPI_ACCESS was selected.)
55          */
56         if (is_shub1())
57                 xp_nofault_PIOR_target = SH1_IPI_ACCESS;
58         else if (is_shub2())
59                 xp_nofault_PIOR_target = SH2_IPI_ACCESS0;
60
61         return xpSuccess;
62 }
63
64 void
65 xp_unregister_nofault_code_sn2(void)
66 {
67         u64 func_addr = *(u64 *)xp_nofault_PIOR;
68         u64 err_func_addr = *(u64 *)xp_error_PIOR;
69
70         /* unregister the PIO read nofault code region */
71         (void)sn_register_nofault_code(func_addr, err_func_addr,
72                                        err_func_addr, 1, 0);
73 }
74
75 enum xp_retval
76 xp_init_sn2(void)
77 {
78         BUG_ON(!is_shub());
79
80         xp_max_npartitions = XP_MAX_NPARTITIONS_SN2;
81
82         return xp_register_nofault_code_sn2();
83 }
84
85 void
86 xp_exit_sn2(void)
87 {
88         BUG_ON(!is_shub());
89
90         xp_unregister_nofault_code_sn2();
91 }
92