xp_main.c 7.0 KB

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