xp_main.c 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287
  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-2008 Silicon Graphics, Inc. All Rights Reserved.
  7. */
  8. /*
  9. * Cross Partition (XP) base.
  10. *
  11. * XP provides a base from which its users can interact
  12. * with XPC, yet not be dependent on XPC.
  13. *
  14. */
  15. #include <linux/module.h>
  16. #include <linux/device.h>
  17. #include "xp.h"
  18. /* define the XP debug device structures to be used with dev_dbg() et al */
  19. struct device_driver xp_dbg_name = {
  20. .name = "xp"
  21. };
  22. struct device xp_dbg_subname = {
  23. .init_name = "", /* set to "" */
  24. .driver = &xp_dbg_name
  25. };
  26. struct device *xp = &xp_dbg_subname;
  27. /* max #of partitions possible */
  28. short xp_max_npartitions;
  29. EXPORT_SYMBOL_GPL(xp_max_npartitions);
  30. short xp_partition_id;
  31. EXPORT_SYMBOL_GPL(xp_partition_id);
  32. u8 xp_region_size;
  33. EXPORT_SYMBOL_GPL(xp_region_size);
  34. unsigned long (*xp_pa) (void *addr);
  35. EXPORT_SYMBOL_GPL(xp_pa);
  36. unsigned long (*xp_socket_pa) (unsigned long gpa);
  37. EXPORT_SYMBOL_GPL(xp_socket_pa);
  38. enum xp_retval (*xp_remote_memcpy) (unsigned long dst_gpa,
  39. const unsigned long src_gpa, size_t len);
  40. EXPORT_SYMBOL_GPL(xp_remote_memcpy);
  41. int (*xp_cpu_to_nasid) (int cpuid);
  42. EXPORT_SYMBOL_GPL(xp_cpu_to_nasid);
  43. enum xp_retval (*xp_expand_memprotect) (unsigned long phys_addr,
  44. unsigned long size);
  45. EXPORT_SYMBOL_GPL(xp_expand_memprotect);
  46. enum xp_retval (*xp_restrict_memprotect) (unsigned long phys_addr,
  47. unsigned long size);
  48. EXPORT_SYMBOL_GPL(xp_restrict_memprotect);
  49. /*
  50. * xpc_registrations[] keeps track of xpc_connect()'s done by the kernel-level
  51. * users of XPC.
  52. */
  53. struct xpc_registration xpc_registrations[XPC_MAX_NCHANNELS];
  54. EXPORT_SYMBOL_GPL(xpc_registrations);
  55. /*
  56. * Initialize the XPC interface to indicate that XPC isn't loaded.
  57. */
  58. static enum xp_retval
  59. xpc_notloaded(void)
  60. {
  61. return xpNotLoaded;
  62. }
  63. struct xpc_interface xpc_interface = {
  64. (void (*)(int))xpc_notloaded,
  65. (void (*)(int))xpc_notloaded,
  66. (enum xp_retval(*)(short, int, u32, void *, u16))xpc_notloaded,
  67. (enum xp_retval(*)(short, int, u32, void *, u16, xpc_notify_func,
  68. void *))xpc_notloaded,
  69. (void (*)(short, int, void *))xpc_notloaded,
  70. (enum xp_retval(*)(short, void *))xpc_notloaded
  71. };
  72. EXPORT_SYMBOL_GPL(xpc_interface);
  73. /*
  74. * XPC calls this when it (the XPC module) has been loaded.
  75. */
  76. void
  77. xpc_set_interface(void (*connect) (int),
  78. void (*disconnect) (int),
  79. enum xp_retval (*send) (short, int, u32, void *, u16),
  80. enum xp_retval (*send_notify) (short, int, u32, void *, u16,
  81. xpc_notify_func, void *),
  82. void (*received) (short, int, void *),
  83. enum xp_retval (*partid_to_nasids) (short, void *))
  84. {
  85. xpc_interface.connect = connect;
  86. xpc_interface.disconnect = disconnect;
  87. xpc_interface.send = send;
  88. xpc_interface.send_notify = send_notify;
  89. xpc_interface.received = received;
  90. xpc_interface.partid_to_nasids = partid_to_nasids;
  91. }
  92. EXPORT_SYMBOL_GPL(xpc_set_interface);
  93. /*
  94. * XPC calls this when it (the XPC module) is being unloaded.
  95. */
  96. void
  97. xpc_clear_interface(void)
  98. {
  99. xpc_interface.connect = (void (*)(int))xpc_notloaded;
  100. xpc_interface.disconnect = (void (*)(int))xpc_notloaded;
  101. xpc_interface.send = (enum xp_retval(*)(short, int, u32, void *, u16))
  102. xpc_notloaded;
  103. xpc_interface.send_notify = (enum xp_retval(*)(short, int, u32, void *,
  104. u16, xpc_notify_func,
  105. void *))xpc_notloaded;
  106. xpc_interface.received = (void (*)(short, int, void *))
  107. xpc_notloaded;
  108. xpc_interface.partid_to_nasids = (enum xp_retval(*)(short, void *))
  109. xpc_notloaded;
  110. }
  111. EXPORT_SYMBOL_GPL(xpc_clear_interface);
  112. /*
  113. * Register for automatic establishment of a channel connection whenever
  114. * a partition comes up.
  115. *
  116. * Arguments:
  117. *
  118. * ch_number - channel # to register for connection.
  119. * func - function to call for asynchronous notification of channel
  120. * state changes (i.e., connection, disconnection, error) and
  121. * the arrival of incoming messages.
  122. * key - pointer to optional user-defined value that gets passed back
  123. * to the user on any callouts made to func.
  124. * payload_size - size in bytes of the XPC message's payload area which
  125. * contains a user-defined message. The user should make
  126. * this large enough to hold their largest message.
  127. * nentries - max #of XPC message entries a message queue can contain.
  128. * The actual number, which is determined when a connection
  129. * is established and may be less then requested, will be
  130. * passed to the user via the xpConnected callout.
  131. * assigned_limit - max number of kthreads allowed to be processing
  132. * messages (per connection) at any given instant.
  133. * idle_limit - max number of kthreads allowed to be idle at any given
  134. * instant.
  135. */
  136. enum xp_retval
  137. xpc_connect(int ch_number, xpc_channel_func func, void *key, u16 payload_size,
  138. u16 nentries, u32 assigned_limit, u32 idle_limit)
  139. {
  140. struct xpc_registration *registration;
  141. DBUG_ON(ch_number < 0 || ch_number >= XPC_MAX_NCHANNELS);
  142. DBUG_ON(payload_size == 0 || nentries == 0);
  143. DBUG_ON(func == NULL);
  144. DBUG_ON(assigned_limit == 0 || idle_limit > assigned_limit);
  145. if (XPC_MSG_SIZE(payload_size) > XPC_MSG_MAX_SIZE)
  146. return xpPayloadTooBig;
  147. registration = &xpc_registrations[ch_number];
  148. if (mutex_lock_interruptible(&registration->mutex) != 0)
  149. return xpInterrupted;
  150. /* if XPC_CHANNEL_REGISTERED(ch_number) */
  151. if (registration->func != NULL) {
  152. mutex_unlock(&registration->mutex);
  153. return xpAlreadyRegistered;
  154. }
  155. /* register the channel for connection */
  156. registration->entry_size = XPC_MSG_SIZE(payload_size);
  157. registration->nentries = nentries;
  158. registration->assigned_limit = assigned_limit;
  159. registration->idle_limit = idle_limit;
  160. registration->key = key;
  161. registration->func = func;
  162. mutex_unlock(&registration->mutex);
  163. xpc_interface.connect(ch_number);
  164. return xpSuccess;
  165. }
  166. EXPORT_SYMBOL_GPL(xpc_connect);
  167. /*
  168. * Remove the registration for automatic connection of the specified channel
  169. * when a partition comes up.
  170. *
  171. * Before returning this xpc_disconnect() will wait for all connections on the
  172. * specified channel have been closed/torndown. So the caller can be assured
  173. * that they will not be receiving any more callouts from XPC to their
  174. * function registered via xpc_connect().
  175. *
  176. * Arguments:
  177. *
  178. * ch_number - channel # to unregister.
  179. */
  180. void
  181. xpc_disconnect(int ch_number)
  182. {
  183. struct xpc_registration *registration;
  184. DBUG_ON(ch_number < 0 || ch_number >= XPC_MAX_NCHANNELS);
  185. registration = &xpc_registrations[ch_number];
  186. /*
  187. * We've decided not to make this a down_interruptible(), since we
  188. * figured XPC's users will just turn around and call xpc_disconnect()
  189. * again anyways, so we might as well wait, if need be.
  190. */
  191. mutex_lock(&registration->mutex);
  192. /* if !XPC_CHANNEL_REGISTERED(ch_number) */
  193. if (registration->func == NULL) {
  194. mutex_unlock(&registration->mutex);
  195. return;
  196. }
  197. /* remove the connection registration for the specified channel */
  198. registration->func = NULL;
  199. registration->key = NULL;
  200. registration->nentries = 0;
  201. registration->entry_size = 0;
  202. registration->assigned_limit = 0;
  203. registration->idle_limit = 0;
  204. xpc_interface.disconnect(ch_number);
  205. mutex_unlock(&registration->mutex);
  206. return;
  207. }
  208. EXPORT_SYMBOL_GPL(xpc_disconnect);
  209. int __init
  210. xp_init(void)
  211. {
  212. enum xp_retval ret;
  213. int ch_number;
  214. /* initialize the connection registration mutex */
  215. for (ch_number = 0; ch_number < XPC_MAX_NCHANNELS; ch_number++)
  216. mutex_init(&xpc_registrations[ch_number].mutex);
  217. if (is_shub())
  218. ret = xp_init_sn2();
  219. else if (is_uv())
  220. ret = xp_init_uv();
  221. else
  222. ret = 0;
  223. if (ret != xpSuccess)
  224. return ret;
  225. return 0;
  226. }
  227. module_init(xp_init);
  228. void __exit
  229. xp_exit(void)
  230. {
  231. if (is_shub())
  232. xp_exit_sn2();
  233. else if (is_uv())
  234. xp_exit_uv();
  235. }
  236. module_exit(xp_exit);
  237. MODULE_AUTHOR("Silicon Graphics, Inc.");
  238. MODULE_DESCRIPTION("Cross Partition (XP) base");
  239. MODULE_LICENSE("GPL");