xp_main.c 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  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. * 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/interrupt.h>
  17. #include <linux/module.h>
  18. #include <asm/sn/intr.h>
  19. #include <asm/sn/sn_sal.h>
  20. #include <asm/sn/xp.h>
  21. /*
  22. * Target of nofault PIO read.
  23. */
  24. u64 xp_nofault_PIOR_target;
  25. /*
  26. * xpc_registrations[] keeps track of xpc_connect()'s done by the kernel-level
  27. * users of XPC.
  28. */
  29. struct xpc_registration xpc_registrations[XPC_NCHANNELS];
  30. /*
  31. * Initialize the XPC interface to indicate that XPC isn't loaded.
  32. */
  33. static enum xpc_retval xpc_notloaded(void) { return xpcNotLoaded; }
  34. struct xpc_interface xpc_interface = {
  35. (void (*)(int)) xpc_notloaded,
  36. (void (*)(int)) xpc_notloaded,
  37. (enum xpc_retval (*)(partid_t, int, u32, void **)) xpc_notloaded,
  38. (enum xpc_retval (*)(partid_t, int, void *)) xpc_notloaded,
  39. (enum xpc_retval (*)(partid_t, int, void *, xpc_notify_func, void *))
  40. xpc_notloaded,
  41. (void (*)(partid_t, int, void *)) xpc_notloaded,
  42. (enum xpc_retval (*)(partid_t, void *)) xpc_notloaded
  43. };
  44. /*
  45. * XPC calls this when it (the XPC module) has been loaded.
  46. */
  47. void
  48. xpc_set_interface(void (*connect)(int),
  49. void (*disconnect)(int),
  50. enum xpc_retval (*allocate)(partid_t, int, u32, void **),
  51. enum xpc_retval (*send)(partid_t, int, void *),
  52. enum xpc_retval (*send_notify)(partid_t, int, void *,
  53. xpc_notify_func, void *),
  54. void (*received)(partid_t, int, void *),
  55. enum xpc_retval (*partid_to_nasids)(partid_t, void *))
  56. {
  57. xpc_interface.connect = connect;
  58. xpc_interface.disconnect = disconnect;
  59. xpc_interface.allocate = allocate;
  60. xpc_interface.send = send;
  61. xpc_interface.send_notify = send_notify;
  62. xpc_interface.received = received;
  63. xpc_interface.partid_to_nasids = partid_to_nasids;
  64. }
  65. /*
  66. * XPC calls this when it (the XPC module) is being unloaded.
  67. */
  68. void
  69. xpc_clear_interface(void)
  70. {
  71. xpc_interface.connect = (void (*)(int)) xpc_notloaded;
  72. xpc_interface.disconnect = (void (*)(int)) xpc_notloaded;
  73. xpc_interface.allocate = (enum xpc_retval (*)(partid_t, int, u32,
  74. void **)) xpc_notloaded;
  75. xpc_interface.send = (enum xpc_retval (*)(partid_t, int, void *))
  76. xpc_notloaded;
  77. xpc_interface.send_notify = (enum xpc_retval (*)(partid_t, int, void *,
  78. xpc_notify_func, void *)) xpc_notloaded;
  79. xpc_interface.received = (void (*)(partid_t, int, void *))
  80. xpc_notloaded;
  81. xpc_interface.partid_to_nasids = (enum xpc_retval (*)(partid_t, void *))
  82. xpc_notloaded;
  83. }
  84. /*
  85. * Register for automatic establishment of a channel connection whenever
  86. * a partition comes up.
  87. *
  88. * Arguments:
  89. *
  90. * ch_number - channel # to register for connection.
  91. * func - function to call for asynchronous notification of channel
  92. * state changes (i.e., connection, disconnection, error) and
  93. * the arrival of incoming messages.
  94. * key - pointer to optional user-defined value that gets passed back
  95. * to the user on any callouts made to func.
  96. * payload_size - size in bytes of the XPC message's payload area which
  97. * contains a user-defined message. The user should make
  98. * this large enough to hold their largest message.
  99. * nentries - max #of XPC message entries a message queue can contain.
  100. * The actual number, which is determined when a connection
  101. * is established and may be less then requested, will be
  102. * passed to the user via the xpcConnected callout.
  103. * assigned_limit - max number of kthreads allowed to be processing
  104. * messages (per connection) at any given instant.
  105. * idle_limit - max number of kthreads allowed to be idle at any given
  106. * instant.
  107. */
  108. enum xpc_retval
  109. xpc_connect(int ch_number, xpc_channel_func func, void *key, u16 payload_size,
  110. u16 nentries, u32 assigned_limit, u32 idle_limit)
  111. {
  112. struct xpc_registration *registration;
  113. DBUG_ON(ch_number < 0 || ch_number >= XPC_NCHANNELS);
  114. DBUG_ON(payload_size == 0 || nentries == 0);
  115. DBUG_ON(func == NULL);
  116. DBUG_ON(assigned_limit == 0 || idle_limit > assigned_limit);
  117. registration = &xpc_registrations[ch_number];
  118. if (down_interruptible(&registration->sema) != 0) {
  119. return xpcInterrupted;
  120. }
  121. /* if XPC_CHANNEL_REGISTERED(ch_number) */
  122. if (registration->func != NULL) {
  123. up(&registration->sema);
  124. return xpcAlreadyRegistered;
  125. }
  126. /* register the channel for connection */
  127. registration->msg_size = XPC_MSG_SIZE(payload_size);
  128. registration->nentries = nentries;
  129. registration->assigned_limit = assigned_limit;
  130. registration->idle_limit = idle_limit;
  131. registration->key = key;
  132. registration->func = func;
  133. up(&registration->sema);
  134. xpc_interface.connect(ch_number);
  135. return xpcSuccess;
  136. }
  137. /*
  138. * Remove the registration for automatic connection of the specified channel
  139. * when a partition comes up.
  140. *
  141. * Before returning this xpc_disconnect() will wait for all connections on the
  142. * specified channel have been closed/torndown. So the caller can be assured
  143. * that they will not be receiving any more callouts from XPC to their
  144. * function registered via xpc_connect().
  145. *
  146. * Arguments:
  147. *
  148. * ch_number - channel # to unregister.
  149. */
  150. void
  151. xpc_disconnect(int ch_number)
  152. {
  153. struct xpc_registration *registration;
  154. DBUG_ON(ch_number < 0 || ch_number >= XPC_NCHANNELS);
  155. registration = &xpc_registrations[ch_number];
  156. /*
  157. * We've decided not to make this a down_interruptible(), since we
  158. * figured XPC's users will just turn around and call xpc_disconnect()
  159. * again anyways, so we might as well wait, if need be.
  160. */
  161. down(&registration->sema);
  162. /* if !XPC_CHANNEL_REGISTERED(ch_number) */
  163. if (registration->func == NULL) {
  164. up(&registration->sema);
  165. return;
  166. }
  167. /* remove the connection registration for the specified channel */
  168. registration->func = NULL;
  169. registration->key = NULL;
  170. registration->nentries = 0;
  171. registration->msg_size = 0;
  172. registration->assigned_limit = 0;
  173. registration->idle_limit = 0;
  174. xpc_interface.disconnect(ch_number);
  175. up(&registration->sema);
  176. return;
  177. }
  178. int __init
  179. xp_init(void)
  180. {
  181. int ret, ch_number;
  182. u64 func_addr = *(u64 *) xp_nofault_PIOR;
  183. u64 err_func_addr = *(u64 *) xp_error_PIOR;
  184. if (!ia64_platform_is("sn2")) {
  185. return -ENODEV;
  186. }
  187. /*
  188. * Register a nofault code region which performs a cross-partition
  189. * PIO read. If the PIO read times out, the MCA handler will consume
  190. * the error and return to a kernel-provided instruction to indicate
  191. * an error. This PIO read exists because it is guaranteed to timeout
  192. * if the destination is down (AMO operations do not timeout on at
  193. * least some CPUs on Shubs <= v1.2, which unfortunately we have to
  194. * work around).
  195. */
  196. if ((ret = sn_register_nofault_code(func_addr, err_func_addr,
  197. err_func_addr, 1, 1)) != 0) {
  198. printk(KERN_ERR "XP: can't register nofault code, error=%d\n",
  199. ret);
  200. }
  201. /*
  202. * Setup the nofault PIO read target. (There is no special reason why
  203. * SH_IPI_ACCESS was selected.)
  204. */
  205. if (is_shub2()) {
  206. xp_nofault_PIOR_target = SH2_IPI_ACCESS0;
  207. } else {
  208. xp_nofault_PIOR_target = SH1_IPI_ACCESS;
  209. }
  210. /* initialize the connection registration semaphores */
  211. for (ch_number = 0; ch_number < XPC_NCHANNELS; ch_number++) {
  212. sema_init(&xpc_registrations[ch_number].sema, 1); /* mutex */
  213. }
  214. return 0;
  215. }
  216. module_init(xp_init);
  217. void __exit
  218. xp_exit(void)
  219. {
  220. u64 func_addr = *(u64 *) xp_nofault_PIOR;
  221. u64 err_func_addr = *(u64 *) xp_error_PIOR;
  222. /* unregister the PIO read nofault code region */
  223. (void) sn_register_nofault_code(func_addr, err_func_addr,
  224. err_func_addr, 1, 0);
  225. }
  226. module_exit(xp_exit);
  227. MODULE_AUTHOR("Silicon Graphics, Inc.");
  228. MODULE_DESCRIPTION("Cross Partition (XP) base");
  229. MODULE_LICENSE("GPL");
  230. EXPORT_SYMBOL(xp_nofault_PIOR);
  231. EXPORT_SYMBOL(xp_nofault_PIOR_target);
  232. EXPORT_SYMBOL(xpc_registrations);
  233. EXPORT_SYMBOL(xpc_interface);
  234. EXPORT_SYMBOL(xpc_clear_interface);
  235. EXPORT_SYMBOL(xpc_set_interface);
  236. EXPORT_SYMBOL(xpc_connect);
  237. EXPORT_SYMBOL(xpc_disconnect);