1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17#include <linux/module.h>
18#include <linux/device.h>
19#include "xp.h"
20
21
22
23struct device_driver xp_dbg_name = {
24 .name = "xp"
25};
26
27struct device xp_dbg_subname = {
28 .bus_id = {0},
29 .driver = &xp_dbg_name
30};
31
32struct device *xp = &xp_dbg_subname;
33
34
35short xp_max_npartitions;
36EXPORT_SYMBOL_GPL(xp_max_npartitions);
37
38short xp_partition_id;
39EXPORT_SYMBOL_GPL(xp_partition_id);
40
41u8 xp_region_size;
42EXPORT_SYMBOL_GPL(xp_region_size);
43
44unsigned long (*xp_pa) (void *addr);
45EXPORT_SYMBOL_GPL(xp_pa);
46
47enum xp_retval (*xp_remote_memcpy) (unsigned long dst_gpa,
48 const unsigned long src_gpa, size_t len);
49EXPORT_SYMBOL_GPL(xp_remote_memcpy);
50
51int (*xp_cpu_to_nasid) (int cpuid);
52EXPORT_SYMBOL_GPL(xp_cpu_to_nasid);
53
54
55
56
57
58struct xpc_registration xpc_registrations[XPC_MAX_NCHANNELS];
59EXPORT_SYMBOL_GPL(xpc_registrations);
60
61
62
63
64static enum xp_retval
65xpc_notloaded(void)
66{
67 return xpNotLoaded;
68}
69
70struct xpc_interface xpc_interface = {
71 (void (*)(int))xpc_notloaded,
72 (void (*)(int))xpc_notloaded,
73 (enum xp_retval(*)(short, int, u32, void *, u16))xpc_notloaded,
74 (enum xp_retval(*)(short, int, u32, void *, u16, xpc_notify_func,
75 void *))xpc_notloaded,
76 (void (*)(short, int, void *))xpc_notloaded,
77 (enum xp_retval(*)(short, void *))xpc_notloaded
78};
79EXPORT_SYMBOL_GPL(xpc_interface);
80
81
82
83
84void
85xpc_set_interface(void (*connect) (int),
86 void (*disconnect) (int),
87 enum xp_retval (*send) (short, int, u32, void *, u16),
88 enum xp_retval (*send_notify) (short, int, u32, void *, u16,
89 xpc_notify_func, void *),
90 void (*received) (short, int, void *),
91 enum xp_retval (*partid_to_nasids) (short, void *))
92{
93 xpc_interface.connect = connect;
94 xpc_interface.disconnect = disconnect;
95 xpc_interface.send = send;
96 xpc_interface.send_notify = send_notify;
97 xpc_interface.received = received;
98 xpc_interface.partid_to_nasids = partid_to_nasids;
99}
100EXPORT_SYMBOL_GPL(xpc_set_interface);
101
102
103
104
105void
106xpc_clear_interface(void)
107{
108 xpc_interface.connect = (void (*)(int))xpc_notloaded;
109 xpc_interface.disconnect = (void (*)(int))xpc_notloaded;
110 xpc_interface.send = (enum xp_retval(*)(short, int, u32, void *, u16))
111 xpc_notloaded;
112 xpc_interface.send_notify = (enum xp_retval(*)(short, int, u32, void *,
113 u16, xpc_notify_func,
114 void *))xpc_notloaded;
115 xpc_interface.received = (void (*)(short, int, void *))
116 xpc_notloaded;
117 xpc_interface.partid_to_nasids = (enum xp_retval(*)(short, void *))
118 xpc_notloaded;
119}
120EXPORT_SYMBOL_GPL(xpc_clear_interface);
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146enum xp_retval
147xpc_connect(int ch_number, xpc_channel_func func, void *key, u16 payload_size,
148 u16 nentries, u32 assigned_limit, u32 idle_limit)
149{
150 struct xpc_registration *registration;
151
152 DBUG_ON(ch_number < 0 || ch_number >= XPC_MAX_NCHANNELS);
153 DBUG_ON(payload_size == 0 || nentries == 0);
154 DBUG_ON(func == NULL);
155 DBUG_ON(assigned_limit == 0 || idle_limit > assigned_limit);
156
157 if (XPC_MSG_SIZE(payload_size) > XPC_MSG_MAX_SIZE)
158 return xpPayloadTooBig;
159
160 registration = &xpc_registrations[ch_number];
161
162 if (mutex_lock_interruptible(®istration->mutex) != 0)
163 return xpInterrupted;
164
165
166 if (registration->func != NULL) {
167 mutex_unlock(®istration->mutex);
168 return xpAlreadyRegistered;
169 }
170
171
172 registration->entry_size = XPC_MSG_SIZE(payload_size);
173 registration->nentries = nentries;
174 registration->assigned_limit = assigned_limit;
175 registration->idle_limit = idle_limit;
176 registration->key = key;
177 registration->func = func;
178
179 mutex_unlock(®istration->mutex);
180
181 xpc_interface.connect(ch_number);
182
183 return xpSuccess;
184}
185EXPORT_SYMBOL_GPL(xpc_connect);
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200void
201xpc_disconnect(int ch_number)
202{
203 struct xpc_registration *registration;
204
205 DBUG_ON(ch_number < 0 || ch_number >= XPC_MAX_NCHANNELS);
206
207 registration = &xpc_registrations[ch_number];
208
209
210
211
212
213
214 mutex_lock(®istration->mutex);
215
216
217 if (registration->func == NULL) {
218 mutex_unlock(®istration->mutex);
219 return;
220 }
221
222
223 registration->func = NULL;
224 registration->key = NULL;
225 registration->nentries = 0;
226 registration->entry_size = 0;
227 registration->assigned_limit = 0;
228 registration->idle_limit = 0;
229
230 xpc_interface.disconnect(ch_number);
231
232 mutex_unlock(®istration->mutex);
233
234 return;
235}
236EXPORT_SYMBOL_GPL(xpc_disconnect);
237
238int __init
239xp_init(void)
240{
241 enum xp_retval ret;
242 int ch_number;
243
244 if (is_shub())
245 ret = xp_init_sn2();
246 else if (is_uv())
247 ret = xp_init_uv();
248 else
249 ret = xpUnsupported;
250
251 if (ret != xpSuccess)
252 return -ENODEV;
253
254
255 for (ch_number = 0; ch_number < XPC_MAX_NCHANNELS; ch_number++)
256 mutex_init(&xpc_registrations[ch_number].mutex);
257
258 return 0;
259}
260
261module_init(xp_init);
262
263void __exit
264xp_exit(void)
265{
266 if (is_shub())
267 xp_exit_sn2();
268 else if (is_uv())
269 xp_exit_uv();
270}
271
272module_exit(xp_exit);
273
274MODULE_AUTHOR("Silicon Graphics, Inc.");
275MODULE_DESCRIPTION("Cross Partition (XP) base");
276MODULE_LICENSE("GPL");
277