aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDean Nelson <dcn@sgi.com>2005-03-23 21:46:00 -0500
committerTony Luck <tony.luck@intel.com>2005-05-03 15:16:52 -0400
commitb0d82bd5df874f7dadbeced1b0163473387da37c (patch)
treec78294ddaff17034ef77253c587a7512ba813e95
parent7fbd2a5337b2aa91266abbded97330f909904fd5 (diff)
[IA64-SGI] SGI Altix cross partition functionality (2nd
This patch contains the shim module (XP) which interfaces between the communication module (XPC) and the functional support modules (like XPNET). Signed-off-by: Dean Nelson <dcn@sgi.com> Signed-off-by: Tony Luck <tony.luck@intel.com>
-rw-r--r--arch/ia64/Kconfig10
-rw-r--r--arch/ia64/sn/kernel/xp_main.c289
-rw-r--r--arch/ia64/sn/kernel/xp_nofault.S31
-rw-r--r--include/asm-ia64/sn/xp.h436
4 files changed, 766 insertions, 0 deletions
diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig
index cad8346def1d..ce13ad689d19 100644
--- a/arch/ia64/Kconfig
+++ b/arch/ia64/Kconfig
@@ -217,6 +217,16 @@ config IA64_SGI_SN_SIM
217 If you are compiling a kernel that will run under SGI's IA-64 217 If you are compiling a kernel that will run under SGI's IA-64
218 simulator (Medusa) then say Y, otherwise say N. 218 simulator (Medusa) then say Y, otherwise say N.
219 219
220config IA64_SGI_SN_XP
221 tristate "Support communication between SGI SSIs"
222 depends on MSPEC
223 help
224 An SGI machine can be divided into multiple Single System
225 Images which act independently of each other and have
226 hardware based memory protection from the others. Enabling
227 this feature will allow for direct communication between SSIs
228 based on a network adapter and DMA messaging.
229
220config FORCE_MAX_ZONEORDER 230config FORCE_MAX_ZONEORDER
221 int 231 int
222 default "18" 232 default "18"
diff --git a/arch/ia64/sn/kernel/xp_main.c b/arch/ia64/sn/kernel/xp_main.c
new file mode 100644
index 000000000000..3be52a34c80f
--- /dev/null
+++ b/arch/ia64/sn/kernel/xp_main.c
@@ -0,0 +1,289 @@
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) 2004-2005 Silicon Graphics, Inc. All Rights Reserved.
7 */
8
9
10/*
11 * Cross Partition (XP) base.
12 *
13 * XP provides a base from which its users can interact
14 * with XPC, yet not be dependent on XPC.
15 *
16 */
17
18
19#include <linux/kernel.h>
20#include <linux/interrupt.h>
21#include <linux/module.h>
22#include <asm/sn/intr.h>
23#include <asm/sn/sn_sal.h>
24#include <asm/sn/xp.h>
25
26
27/*
28 * Target of nofault PIO read.
29 */
30u64 xp_nofault_PIOR_target;
31
32
33/*
34 * xpc_registrations[] keeps track of xpc_connect()'s done by the kernel-level
35 * users of XPC.
36 */
37struct xpc_registration xpc_registrations[XPC_NCHANNELS];
38
39
40/*
41 * Initialize the XPC interface to indicate that XPC isn't loaded.
42 */
43static enum xpc_retval xpc_notloaded(void) { return xpcNotLoaded; }
44
45struct xpc_interface xpc_interface = {
46 (void (*)(int)) xpc_notloaded,
47 (void (*)(int)) xpc_notloaded,
48 (enum xpc_retval (*)(partid_t, int, u32, void **)) xpc_notloaded,
49 (enum xpc_retval (*)(partid_t, int, void *)) xpc_notloaded,
50 (enum xpc_retval (*)(partid_t, int, void *, xpc_notify_func, void *))
51 xpc_notloaded,
52 (void (*)(partid_t, int, void *)) xpc_notloaded,
53 (enum xpc_retval (*)(partid_t, void *)) xpc_notloaded
54};
55
56
57/*
58 * XPC calls this when it (the XPC module) has been loaded.
59 */
60void
61xpc_set_interface(void (*connect)(int),
62 void (*disconnect)(int),
63 enum xpc_retval (*allocate)(partid_t, int, u32, void **),
64 enum xpc_retval (*send)(partid_t, int, void *),
65 enum xpc_retval (*send_notify)(partid_t, int, void *,
66 xpc_notify_func, void *),
67 void (*received)(partid_t, int, void *),
68 enum xpc_retval (*partid_to_nasids)(partid_t, void *))
69{
70 xpc_interface.connect = connect;
71 xpc_interface.disconnect = disconnect;
72 xpc_interface.allocate = allocate;
73 xpc_interface.send = send;
74 xpc_interface.send_notify = send_notify;
75 xpc_interface.received = received;
76 xpc_interface.partid_to_nasids = partid_to_nasids;
77}
78
79
80/*
81 * XPC calls this when it (the XPC module) is being unloaded.
82 */
83void
84xpc_clear_interface(void)
85{
86 xpc_interface.connect = (void (*)(int)) xpc_notloaded;
87 xpc_interface.disconnect = (void (*)(int)) xpc_notloaded;
88 xpc_interface.allocate = (enum xpc_retval (*)(partid_t, int, u32,
89 void **)) xpc_notloaded;
90 xpc_interface.send = (enum xpc_retval (*)(partid_t, int, void *))
91 xpc_notloaded;
92 xpc_interface.send_notify = (enum xpc_retval (*)(partid_t, int, void *,
93 xpc_notify_func, void *)) xpc_notloaded;
94 xpc_interface.received = (void (*)(partid_t, int, void *))
95 xpc_notloaded;
96 xpc_interface.partid_to_nasids = (enum xpc_retval (*)(partid_t, void *))
97 xpc_notloaded;
98}
99
100
101/*
102 * Register for automatic establishment of a channel connection whenever
103 * a partition comes up.
104 *
105 * Arguments:
106 *
107 * ch_number - channel # to register for connection.
108 * func - function to call for asynchronous notification of channel
109 * state changes (i.e., connection, disconnection, error) and
110 * the arrival of incoming messages.
111 * key - pointer to optional user-defined value that gets passed back
112 * to the user on any callouts made to func.
113 * payload_size - size in bytes of the XPC message's payload area which
114 * contains a user-defined message. The user should make
115 * this large enough to hold their largest message.
116 * nentries - max #of XPC message entries a message queue can contain.
117 * The actual number, which is determined when a connection
118 * is established and may be less then requested, will be
119 * passed to the user via the xpcConnected callout.
120 * assigned_limit - max number of kthreads allowed to be processing
121 * messages (per connection) at any given instant.
122 * idle_limit - max number of kthreads allowed to be idle at any given
123 * instant.
124 */
125enum xpc_retval
126xpc_connect(int ch_number, xpc_channel_func func, void *key, u16 payload_size,
127 u16 nentries, u32 assigned_limit, u32 idle_limit)
128{
129 struct xpc_registration *registration;
130
131
132 DBUG_ON(ch_number < 0 || ch_number >= XPC_NCHANNELS);
133 DBUG_ON(payload_size == 0 || nentries == 0);
134 DBUG_ON(func == NULL);
135 DBUG_ON(assigned_limit == 0 || idle_limit > assigned_limit);
136
137 registration = &xpc_registrations[ch_number];
138
139 if (down_interruptible(&registration->sema) != 0) {
140 return xpcInterrupted;
141 }
142
143 /* if XPC_CHANNEL_REGISTERED(ch_number) */
144 if (registration->func != NULL) {
145 up(&registration->sema);
146 return xpcAlreadyRegistered;
147 }
148
149 /* register the channel for connection */
150 registration->msg_size = XPC_MSG_SIZE(payload_size);
151 registration->nentries = nentries;
152 registration->assigned_limit = assigned_limit;
153 registration->idle_limit = idle_limit;
154 registration->key = key;
155 registration->func = func;
156
157 up(&registration->sema);
158
159 xpc_interface.connect(ch_number);
160
161 return xpcSuccess;
162}
163
164
165/*
166 * Remove the registration for automatic connection of the specified channel
167 * when a partition comes up.
168 *
169 * Before returning this xpc_disconnect() will wait for all connections on the
170 * specified channel have been closed/torndown. So the caller can be assured
171 * that they will not be receiving any more callouts from XPC to their
172 * function registered via xpc_connect().
173 *
174 * Arguments:
175 *
176 * ch_number - channel # to unregister.
177 */
178void
179xpc_disconnect(int ch_number)
180{
181 struct xpc_registration *registration;
182
183
184 DBUG_ON(ch_number < 0 || ch_number >= XPC_NCHANNELS);
185
186 registration = &xpc_registrations[ch_number];
187
188 /*
189 * We've decided not to make this a down_interruptible(), since we
190 * figured XPC's users will just turn around and call xpc_disconnect()
191 * again anyways, so we might as well wait, if need be.
192 */
193 down(&registration->sema);
194
195 /* if !XPC_CHANNEL_REGISTERED(ch_number) */
196 if (registration->func == NULL) {
197 up(&registration->sema);
198 return;
199 }
200
201 /* remove the connection registration for the specified channel */
202 registration->func = NULL;
203 registration->key = NULL;
204 registration->nentries = 0;
205 registration->msg_size = 0;
206 registration->assigned_limit = 0;
207 registration->idle_limit = 0;
208
209 xpc_interface.disconnect(ch_number);
210
211 up(&registration->sema);
212
213 return;
214}
215
216
217int __init
218xp_init(void)
219{
220 int ret, ch_number;
221 u64 func_addr = *(u64 *) xp_nofault_PIOR;
222 u64 err_func_addr = *(u64 *) xp_error_PIOR;
223
224
225 if (!ia64_platform_is("sn2")) {
226 return -ENODEV;
227 }
228
229 /*
230 * Register a nofault code region which performs a cross-partition
231 * PIO read. If the PIO read times out, the MCA handler will consume
232 * the error and return to a kernel-provided instruction to indicate
233 * an error. This PIO read exists because it is guaranteed to timeout
234 * if the destination is down (AMO operations do not timeout on at
235 * least some CPUs on Shubs <= v1.2, which unfortunately we have to
236 * work around).
237 */
238 if ((ret = sn_register_nofault_code(func_addr, err_func_addr,
239 err_func_addr, 1, 1)) != 0) {
240 printk(KERN_ERR "XP: can't register nofault code, error=%d\n",
241 ret);
242 }
243 /*
244 * Setup the nofault PIO read target. (There is no special reason why
245 * SH_IPI_ACCESS was selected.)
246 */
247 if (is_shub2()) {
248 xp_nofault_PIOR_target = SH2_IPI_ACCESS0;
249 } else {
250 xp_nofault_PIOR_target = SH1_IPI_ACCESS;
251 }
252
253 /* initialize the connection registration semaphores */
254 for (ch_number = 0; ch_number < XPC_NCHANNELS; ch_number++) {
255 sema_init(&xpc_registrations[ch_number].sema, 1); /* mutex */
256 }
257
258 return 0;
259}
260module_init(xp_init);
261
262
263void __exit
264xp_exit(void)
265{
266 u64 func_addr = *(u64 *) xp_nofault_PIOR;
267 u64 err_func_addr = *(u64 *) xp_error_PIOR;
268
269
270 /* unregister the PIO read nofault code region */
271 (void) sn_register_nofault_code(func_addr, err_func_addr,
272 err_func_addr, 1, 0);
273}
274module_exit(xp_exit);
275
276
277MODULE_AUTHOR("Silicon Graphics, Inc.");
278MODULE_DESCRIPTION("Cross Partition (XP) base");
279MODULE_LICENSE("GPL");
280
281EXPORT_SYMBOL(xp_nofault_PIOR);
282EXPORT_SYMBOL(xp_nofault_PIOR_target);
283EXPORT_SYMBOL(xpc_registrations);
284EXPORT_SYMBOL(xpc_interface);
285EXPORT_SYMBOL(xpc_clear_interface);
286EXPORT_SYMBOL(xpc_set_interface);
287EXPORT_SYMBOL(xpc_connect);
288EXPORT_SYMBOL(xpc_disconnect);
289
diff --git a/arch/ia64/sn/kernel/xp_nofault.S b/arch/ia64/sn/kernel/xp_nofault.S
new file mode 100644
index 000000000000..b772543053c9
--- /dev/null
+++ b/arch/ia64/sn/kernel/xp_nofault.S
@@ -0,0 +1,31 @@
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) 2004-2005 Silicon Graphics, Inc. All Rights Reserved.
7 */
8
9
10/*
11 * The xp_nofault_PIOR function takes a pointer to a remote PIO register
12 * and attempts to load and consume a value from it. This function
13 * will be registered as a nofault code block. In the event that the
14 * PIO read fails, the MCA handler will force the error to look
15 * corrected and vector to the xp_error_PIOR which will return an error.
16 *
17 * extern int xp_nofault_PIOR(void *remote_register);
18 */
19
20 .global xp_nofault_PIOR
21xp_nofault_PIOR:
22 mov r8=r0 // Stage a success return value
23 ld8.acq r9=[r32];; // PIO Read the specified register
24 adds r9=1,r9 // Add to force a consume
25 br.ret.sptk.many b0;; // Return success
26
27 .global xp_error_PIOR
28xp_error_PIOR:
29 mov r8=1 // Return value of 1
30 br.ret.sptk.many b0;; // Return failure
31
diff --git a/include/asm-ia64/sn/xp.h b/include/asm-ia64/sn/xp.h
new file mode 100644
index 000000000000..9902185c0288
--- /dev/null
+++ b/include/asm-ia64/sn/xp.h
@@ -0,0 +1,436 @@
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) 2004-2005 Silicon Graphics, Inc. All rights reserved.
7 */
8
9
10/*
11 * External Cross Partition (XP) structures and defines.
12 */
13
14
15#ifndef _ASM_IA64_SN_XP_H
16#define _ASM_IA64_SN_XP_H
17
18
19#include <linux/version.h>
20#include <linux/cache.h>
21#include <linux/hardirq.h>
22#include <asm/sn/types.h>
23#include <asm/sn/bte.h>
24
25
26#ifdef USE_DBUG_ON
27#define DBUG_ON(condition) BUG_ON(condition)
28#else
29#define DBUG_ON(condition)
30#endif
31
32
33/*
34 * Define the maximum number of logically defined partitions the system
35 * can support. It is constrained by the maximum number of hardware
36 * partitionable regions. The term 'region' in this context refers to the
37 * minimum number of nodes that can comprise an access protection grouping.
38 * The access protection is in regards to memory, IPI and IOI.
39 *
40 * The maximum number of hardware partitionable regions is equal to the
41 * maximum number of nodes in the entire system divided by the minimum number
42 * of nodes that comprise an access protection grouping.
43 */
44#define XP_MAX_PARTITIONS 64
45
46
47/*
48 * Define the number of u64s required to represent all the C-brick nasids
49 * as a bitmap. The cross-partition kernel modules deal only with
50 * C-brick nasids, thus the need for bitmaps which don't account for
51 * odd-numbered (non C-brick) nasids.
52 */
53#define XP_MAX_PHYSNODE_ID (MAX_PHYSNODE_ID / 2)
54#define XP_NASID_MASK_BYTES ((XP_MAX_PHYSNODE_ID + 7) / 8)
55#define XP_NASID_MASK_WORDS ((XP_MAX_PHYSNODE_ID + 63) / 64)
56
57
58/*
59 * Wrapper for bte_copy() that should it return a failure status will retry
60 * the bte_copy() once in the hope that the failure was due to a temporary
61 * aberration (i.e., the link going down temporarily).
62 *
63 * See bte_copy for definition of the input parameters.
64 *
65 * Note: xp_bte_copy() should never be called while holding a spinlock.
66 */
67static inline bte_result_t
68xp_bte_copy(u64 src, u64 dest, u64 len, u64 mode, void *notification)
69{
70 bte_result_t ret;
71
72
73 ret = bte_copy(src, dest, len, mode, notification);
74
75 if (ret != BTE_SUCCESS) {
76 if (!in_interrupt()) {
77 cond_resched();
78 }
79 ret = bte_copy(src, dest, len, mode, notification);
80 }
81
82 return ret;
83}
84
85
86/*
87 * XPC establishes channel connections between the local partition and any
88 * other partition that is currently up. Over these channels, kernel-level
89 * `users' can communicate with their counterparts on the other partitions.
90 *
91 * The maxinum number of channels is limited to eight. For performance reasons,
92 * the internal cross partition structures require sixteen bytes per channel,
93 * and eight allows all of this interface-shared info to fit in one cache line.
94 *
95 * XPC_NCHANNELS reflects the total number of channels currently defined.
96 * If the need for additional channels arises, one can simply increase
97 * XPC_NCHANNELS accordingly. If the day should come where that number
98 * exceeds the MAXIMUM number of channels allowed (eight), then one will need
99 * to make changes to the XPC code to allow for this.
100 */
101#define XPC_MEM_CHANNEL 0 /* memory channel number */
102#define XPC_NET_CHANNEL 1 /* network channel number */
103
104#define XPC_NCHANNELS 2 /* #of defined channels */
105#define XPC_MAX_NCHANNELS 8 /* max #of channels allowed */
106
107#if XPC_NCHANNELS > XPC_MAX_NCHANNELS
108#error XPC_NCHANNELS exceeds MAXIMUM allowed.
109#endif
110
111
112/*
113 * The format of an XPC message is as follows:
114 *
115 * +-------+--------------------------------+
116 * | flags |////////////////////////////////|
117 * +-------+--------------------------------+
118 * | message # |
119 * +----------------------------------------+
120 * | payload (user-defined message) |
121 * | |
122 * :
123 * | |
124 * +----------------------------------------+
125 *
126 * The size of the payload is defined by the user via xpc_connect(). A user-
127 * defined message resides in the payload area.
128 *
129 * The user should have no dealings with the message header, but only the
130 * message's payload. When a message entry is allocated (via xpc_allocate())
131 * a pointer to the payload area is returned and not the actual beginning of
132 * the XPC message. The user then constructs a message in the payload area
133 * and passes that pointer as an argument on xpc_send() or xpc_send_notify().
134 *
135 * The size of a message entry (within a message queue) must be a cacheline
136 * sized multiple in order to facilitate the BTE transfer of messages from one
137 * message queue to another. A macro, XPC_MSG_SIZE(), is provided for the user
138 * that wants to fit as many msg entries as possible in a given memory size
139 * (e.g. a memory page).
140 */
141struct xpc_msg {
142 u8 flags; /* FOR XPC INTERNAL USE ONLY */
143 u8 reserved[7]; /* FOR XPC INTERNAL USE ONLY */
144 s64 number; /* FOR XPC INTERNAL USE ONLY */
145
146 u64 payload; /* user defined portion of message */
147};
148
149
150#define XPC_MSG_PAYLOAD_OFFSET (u64) (&((struct xpc_msg *)0)->payload)
151#define XPC_MSG_SIZE(_payload_size) \
152 L1_CACHE_ALIGN(XPC_MSG_PAYLOAD_OFFSET + (_payload_size))
153
154
155/*
156 * Define the return values and values passed to user's callout functions.
157 * (It is important to add new value codes at the end just preceding
158 * xpcUnknownReason, which must have the highest numerical value.)
159 */
160enum xpc_retval {
161 xpcSuccess = 0,
162
163 xpcNotConnected, /* 1: channel is not connected */
164 xpcConnected, /* 2: channel connected (opened) */
165 xpcRETIRED1, /* 3: (formerly xpcDisconnected) */
166
167 xpcMsgReceived, /* 4: message received */
168 xpcMsgDelivered, /* 5: message delivered and acknowledged */
169
170 xpcRETIRED2, /* 6: (formerly xpcTransferFailed) */
171
172 xpcNoWait, /* 7: operation would require wait */
173 xpcRetry, /* 8: retry operation */
174 xpcTimeout, /* 9: timeout in xpc_allocate_msg_wait() */
175 xpcInterrupted, /* 10: interrupted wait */
176
177 xpcUnequalMsgSizes, /* 11: message size disparity between sides */
178 xpcInvalidAddress, /* 12: invalid address */
179
180 xpcNoMemory, /* 13: no memory available for XPC structures */
181 xpcLackOfResources, /* 14: insufficient resources for operation */
182 xpcUnregistered, /* 15: channel is not registered */
183 xpcAlreadyRegistered, /* 16: channel is already registered */
184
185 xpcPartitionDown, /* 17: remote partition is down */
186 xpcNotLoaded, /* 18: XPC module is not loaded */
187 xpcUnloading, /* 19: this side is unloading XPC module */
188
189 xpcBadMagic, /* 20: XPC MAGIC string not found */
190
191 xpcReactivating, /* 21: remote partition was reactivated */
192
193 xpcUnregistering, /* 22: this side is unregistering channel */
194 xpcOtherUnregistering, /* 23: other side is unregistering channel */
195
196 xpcCloneKThread, /* 24: cloning kernel thread */
197 xpcCloneKThreadFailed, /* 25: cloning kernel thread failed */
198
199 xpcNoHeartbeat, /* 26: remote partition has no heartbeat */
200
201 xpcPioReadError, /* 27: PIO read error */
202 xpcPhysAddrRegFailed, /* 28: registration of phys addr range failed */
203
204 xpcBteDirectoryError, /* 29: maps to BTEFAIL_DIR */
205 xpcBtePoisonError, /* 30: maps to BTEFAIL_POISON */
206 xpcBteWriteError, /* 31: maps to BTEFAIL_WERR */
207 xpcBteAccessError, /* 32: maps to BTEFAIL_ACCESS */
208 xpcBtePWriteError, /* 33: maps to BTEFAIL_PWERR */
209 xpcBtePReadError, /* 34: maps to BTEFAIL_PRERR */
210 xpcBteTimeOutError, /* 35: maps to BTEFAIL_TOUT */
211 xpcBteXtalkError, /* 36: maps to BTEFAIL_XTERR */
212 xpcBteNotAvailable, /* 37: maps to BTEFAIL_NOTAVAIL */
213 xpcBteUnmappedError, /* 38: unmapped BTEFAIL_ error */
214
215 xpcBadVersion, /* 39: bad version number */
216 xpcVarsNotSet, /* 40: the XPC variables are not set up */
217 xpcNoRsvdPageAddr, /* 41: unable to get rsvd page's phys addr */
218 xpcInvalidPartid, /* 42: invalid partition ID */
219 xpcLocalPartid, /* 43: local partition ID */
220
221 xpcUnknownReason /* 44: unknown reason -- must be last in list */
222};
223
224
225/*
226 * Define the callout function types used by XPC to update the user on
227 * connection activity and state changes (via the user function registered by
228 * xpc_connect()) and to notify them of messages received and delivered (via
229 * the user function registered by xpc_send_notify()).
230 *
231 * The two function types are xpc_channel_func and xpc_notify_func and
232 * both share the following arguments, with the exception of "data", which
233 * only xpc_channel_func has.
234 *
235 * Arguments:
236 *
237 * reason - reason code. (See following table.)
238 * partid - partition ID associated with condition.
239 * ch_number - channel # associated with condition.
240 * data - pointer to optional data. (See following table.)
241 * key - pointer to optional user-defined value provided as the "key"
242 * argument to xpc_connect() or xpc_send_notify().
243 *
244 * In the following table the "Optional Data" column applies to callouts made
245 * to functions registered by xpc_connect(). A "NA" in that column indicates
246 * that this reason code can be passed to functions registered by
247 * xpc_send_notify() (i.e. they don't have data arguments).
248 *
249 * Also, the first three reason codes in the following table indicate
250 * success, whereas the others indicate failure. When a failure reason code
251 * is received, one can assume that the channel is not connected.
252 *
253 *
254 * Reason Code | Cause | Optional Data
255 * =====================+================================+=====================
256 * xpcConnected | connection has been established| max #of entries
257 * | to the specified partition on | allowed in message
258 * | the specified channel | queue
259 * ---------------------+--------------------------------+---------------------
260 * xpcMsgReceived | an XPC message arrived from | address of payload
261 * | the specified partition on the |
262 * | specified channel | [the user must call
263 * | | xpc_received() when
264 * | | finished with the
265 * | | payload]
266 * ---------------------+--------------------------------+---------------------
267 * xpcMsgDelivered | notification that the message | NA
268 * | was delivered to the intended |
269 * | recipient and that they have |
270 * | acknowledged its receipt by |
271 * | calling xpc_received() |
272 * =====================+================================+=====================
273 * xpcUnequalMsgSizes | can't connect to the specified | NULL
274 * | partition on the specified |
275 * | channel because of mismatched |
276 * | message sizes |
277 * ---------------------+--------------------------------+---------------------
278 * xpcNoMemory | insufficient memory avaiable | NULL
279 * | to allocate message queue |
280 * ---------------------+--------------------------------+---------------------
281 * xpcLackOfResources | lack of resources to create | NULL
282 * | the necessary kthreads to |
283 * | support the channel |
284 * ---------------------+--------------------------------+---------------------
285 * xpcUnregistering | this side's user has | NULL or NA
286 * | unregistered by calling |
287 * | xpc_disconnect() |
288 * ---------------------+--------------------------------+---------------------
289 * xpcOtherUnregistering| the other side's user has | NULL or NA
290 * | unregistered by calling |
291 * | xpc_disconnect() |
292 * ---------------------+--------------------------------+---------------------
293 * xpcNoHeartbeat | the other side's XPC is no | NULL or NA
294 * | longer heartbeating |
295 * | |
296 * ---------------------+--------------------------------+---------------------
297 * xpcUnloading | this side's XPC module is | NULL or NA
298 * | being unloaded |
299 * | |
300 * ---------------------+--------------------------------+---------------------
301 * xpcOtherUnloading | the other side's XPC module is | NULL or NA
302 * | is being unloaded |
303 * | |
304 * ---------------------+--------------------------------+---------------------
305 * xpcPioReadError | xp_nofault_PIOR() returned an | NULL or NA
306 * | error while sending an IPI |
307 * | |
308 * ---------------------+--------------------------------+---------------------
309 * xpcInvalidAddress | the address either received or | NULL or NA
310 * | sent by the specified partition|
311 * | is invalid |
312 * ---------------------+--------------------------------+---------------------
313 * xpcBteNotAvailable | attempt to pull data from the | NULL or NA
314 * xpcBtePoisonError | specified partition over the |
315 * xpcBteWriteError | specified channel via a |
316 * xpcBteAccessError | bte_copy() failed |
317 * xpcBteTimeOutError | |
318 * xpcBteXtalkError | |
319 * xpcBteDirectoryError | |
320 * xpcBteGenericError | |
321 * xpcBteUnmappedError | |
322 * ---------------------+--------------------------------+---------------------
323 * xpcUnknownReason | the specified channel to the | NULL or NA
324 * | specified partition was |
325 * | unavailable for unknown reasons|
326 * =====================+================================+=====================
327 */
328
329typedef void (*xpc_channel_func)(enum xpc_retval reason, partid_t partid,
330 int ch_number, void *data, void *key);
331
332typedef void (*xpc_notify_func)(enum xpc_retval reason, partid_t partid,
333 int ch_number, void *key);
334
335
336/*
337 * The following is a registration entry. There is a global array of these,
338 * one per channel. It is used to record the connection registration made
339 * by the users of XPC. As long as a registration entry exists, for any
340 * partition that comes up, XPC will attempt to establish a connection on
341 * that channel. Notification that a connection has been made will occur via
342 * the xpc_channel_func function.
343 *
344 * The 'func' field points to the function to call when aynchronous
345 * notification is required for such events as: a connection established/lost,
346 * or an incomming message received, or an error condition encountered. A
347 * non-NULL 'func' field indicates that there is an active registration for
348 * the channel.
349 */
350struct xpc_registration {
351 struct semaphore sema;
352 xpc_channel_func func; /* function to call */
353 void *key; /* pointer to user's key */
354 u16 nentries; /* #of msg entries in local msg queue */
355 u16 msg_size; /* message queue's message size */
356 u32 assigned_limit; /* limit on #of assigned kthreads */
357 u32 idle_limit; /* limit on #of idle kthreads */
358} ____cacheline_aligned;
359
360
361#define XPC_CHANNEL_REGISTERED(_c) (xpc_registrations[_c].func != NULL)
362
363
364/* the following are valid xpc_allocate() flags */
365#define XPC_WAIT 0 /* wait flag */
366#define XPC_NOWAIT 1 /* no wait flag */
367
368
369struct xpc_interface {
370 void (*connect)(int);
371 void (*disconnect)(int);
372 enum xpc_retval (*allocate)(partid_t, int, u32, void **);
373 enum xpc_retval (*send)(partid_t, int, void *);
374 enum xpc_retval (*send_notify)(partid_t, int, void *,
375 xpc_notify_func, void *);
376 void (*received)(partid_t, int, void *);
377 enum xpc_retval (*partid_to_nasids)(partid_t, void *);
378};
379
380
381extern struct xpc_interface xpc_interface;
382
383extern void xpc_set_interface(void (*)(int),
384 void (*)(int),
385 enum xpc_retval (*)(partid_t, int, u32, void **),
386 enum xpc_retval (*)(partid_t, int, void *),
387 enum xpc_retval (*)(partid_t, int, void *, xpc_notify_func,
388 void *),
389 void (*)(partid_t, int, void *),
390 enum xpc_retval (*)(partid_t, void *));
391extern void xpc_clear_interface(void);
392
393
394extern enum xpc_retval xpc_connect(int, xpc_channel_func, void *, u16,
395 u16, u32, u32);
396extern void xpc_disconnect(int);
397
398static inline enum xpc_retval
399xpc_allocate(partid_t partid, int ch_number, u32 flags, void **payload)
400{
401 return xpc_interface.allocate(partid, ch_number, flags, payload);
402}
403
404static inline enum xpc_retval
405xpc_send(partid_t partid, int ch_number, void *payload)
406{
407 return xpc_interface.send(partid, ch_number, payload);
408}
409
410static inline enum xpc_retval
411xpc_send_notify(partid_t partid, int ch_number, void *payload,
412 xpc_notify_func func, void *key)
413{
414 return xpc_interface.send_notify(partid, ch_number, payload, func, key);
415}
416
417static inline void
418xpc_received(partid_t partid, int ch_number, void *payload)
419{
420 return xpc_interface.received(partid, ch_number, payload);
421}
422
423static inline enum xpc_retval
424xpc_partid_to_nasids(partid_t partid, void *nasids)
425{
426 return xpc_interface.partid_to_nasids(partid, nasids);
427}
428
429
430extern u64 xp_nofault_PIOR_target;
431extern int xp_nofault_PIOR(void *);
432extern int xp_error_PIOR(void);
433
434
435#endif /* _ASM_IA64_SN_XP_H */
436