xp_main.c 7.2 KB

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