xpc_uv.c 45 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728
  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) 2008-2009 Silicon Graphics, Inc. All Rights Reserved.
  7. */
  8. /*
  9. * Cross Partition Communication (XPC) uv-based functions.
  10. *
  11. * Architecture specific implementation of common functions.
  12. *
  13. */
  14. #include <linux/kernel.h>
  15. #include <linux/mm.h>
  16. #include <linux/interrupt.h>
  17. #include <linux/delay.h>
  18. #include <linux/device.h>
  19. #include <linux/cpu.h>
  20. #include <linux/module.h>
  21. #include <linux/err.h>
  22. #include <linux/slab.h>
  23. #include <linux/numa.h>
  24. #include <asm/uv/uv_hub.h>
  25. #include <asm/uv/bios.h>
  26. #include <asm/uv/uv_irq.h>
  27. #include "../sgi-gru/gru.h"
  28. #include "../sgi-gru/grukservices.h"
  29. #include "xpc.h"
  30. static struct xpc_heartbeat_uv *xpc_heartbeat_uv;
  31. #define XPC_ACTIVATE_MSG_SIZE_UV (1 * GRU_CACHE_LINE_BYTES)
  32. #define XPC_ACTIVATE_MQ_SIZE_UV (4 * XP_MAX_NPARTITIONS_UV * \
  33. XPC_ACTIVATE_MSG_SIZE_UV)
  34. #define XPC_ACTIVATE_IRQ_NAME "xpc_activate"
  35. #define XPC_NOTIFY_MSG_SIZE_UV (2 * GRU_CACHE_LINE_BYTES)
  36. #define XPC_NOTIFY_MQ_SIZE_UV (4 * XP_MAX_NPARTITIONS_UV * \
  37. XPC_NOTIFY_MSG_SIZE_UV)
  38. #define XPC_NOTIFY_IRQ_NAME "xpc_notify"
  39. static int xpc_mq_node = NUMA_NO_NODE;
  40. static struct xpc_gru_mq_uv *xpc_activate_mq_uv;
  41. static struct xpc_gru_mq_uv *xpc_notify_mq_uv;
  42. static int
  43. xpc_setup_partitions_uv(void)
  44. {
  45. short partid;
  46. struct xpc_partition_uv *part_uv;
  47. for (partid = 0; partid < XP_MAX_NPARTITIONS_UV; partid++) {
  48. part_uv = &xpc_partitions[partid].sn.uv;
  49. mutex_init(&part_uv->cached_activate_gru_mq_desc_mutex);
  50. spin_lock_init(&part_uv->flags_lock);
  51. part_uv->remote_act_state = XPC_P_AS_INACTIVE;
  52. }
  53. return 0;
  54. }
  55. static void
  56. xpc_teardown_partitions_uv(void)
  57. {
  58. short partid;
  59. struct xpc_partition_uv *part_uv;
  60. unsigned long irq_flags;
  61. for (partid = 0; partid < XP_MAX_NPARTITIONS_UV; partid++) {
  62. part_uv = &xpc_partitions[partid].sn.uv;
  63. if (part_uv->cached_activate_gru_mq_desc != NULL) {
  64. mutex_lock(&part_uv->cached_activate_gru_mq_desc_mutex);
  65. spin_lock_irqsave(&part_uv->flags_lock, irq_flags);
  66. part_uv->flags &= ~XPC_P_CACHED_ACTIVATE_GRU_MQ_DESC_UV;
  67. spin_unlock_irqrestore(&part_uv->flags_lock, irq_flags);
  68. kfree(part_uv->cached_activate_gru_mq_desc);
  69. part_uv->cached_activate_gru_mq_desc = NULL;
  70. mutex_unlock(&part_uv->
  71. cached_activate_gru_mq_desc_mutex);
  72. }
  73. }
  74. }
  75. static int
  76. xpc_get_gru_mq_irq_uv(struct xpc_gru_mq_uv *mq, int cpu, char *irq_name)
  77. {
  78. int mmr_pnode = uv_blade_to_pnode(mq->mmr_blade);
  79. mq->irq = uv_setup_irq(irq_name, cpu, mq->mmr_blade, mq->mmr_offset,
  80. UV_AFFINITY_CPU);
  81. if (mq->irq < 0)
  82. return mq->irq;
  83. mq->mmr_value = uv_read_global_mmr64(mmr_pnode, mq->mmr_offset);
  84. return 0;
  85. }
  86. static void
  87. xpc_release_gru_mq_irq_uv(struct xpc_gru_mq_uv *mq)
  88. {
  89. uv_teardown_irq(mq->irq);
  90. }
  91. static int
  92. xpc_gru_mq_watchlist_alloc_uv(struct xpc_gru_mq_uv *mq)
  93. {
  94. int ret;
  95. ret = uv_bios_mq_watchlist_alloc(uv_gpa(mq->address),
  96. mq->order, &mq->mmr_offset);
  97. if (ret < 0) {
  98. dev_err(xpc_part, "uv_bios_mq_watchlist_alloc() failed, "
  99. "ret=%d\n", ret);
  100. return ret;
  101. }
  102. mq->watchlist_num = ret;
  103. return 0;
  104. }
  105. static void
  106. xpc_gru_mq_watchlist_free_uv(struct xpc_gru_mq_uv *mq)
  107. {
  108. int ret;
  109. int mmr_pnode = uv_blade_to_pnode(mq->mmr_blade);
  110. ret = uv_bios_mq_watchlist_free(mmr_pnode, mq->watchlist_num);
  111. BUG_ON(ret != BIOS_STATUS_SUCCESS);
  112. }
  113. static struct xpc_gru_mq_uv *
  114. xpc_create_gru_mq_uv(unsigned int mq_size, int cpu, char *irq_name,
  115. irq_handler_t irq_handler)
  116. {
  117. enum xp_retval xp_ret;
  118. int ret;
  119. int nid;
  120. int nasid;
  121. int pg_order;
  122. struct page *page;
  123. struct xpc_gru_mq_uv *mq;
  124. struct uv_IO_APIC_route_entry *mmr_value;
  125. mq = kmalloc_obj(struct xpc_gru_mq_uv);
  126. if (mq == NULL) {
  127. dev_err(xpc_part, "xpc_create_gru_mq_uv() failed to kmalloc() "
  128. "a xpc_gru_mq_uv structure\n");
  129. ret = -ENOMEM;
  130. goto out_0;
  131. }
  132. mq->gru_mq_desc = kzalloc_obj(struct gru_message_queue_desc);
  133. if (mq->gru_mq_desc == NULL) {
  134. dev_err(xpc_part, "xpc_create_gru_mq_uv() failed to kmalloc() "
  135. "a gru_message_queue_desc structure\n");
  136. ret = -ENOMEM;
  137. goto out_1;
  138. }
  139. pg_order = get_order(mq_size);
  140. mq->order = pg_order + PAGE_SHIFT;
  141. mq_size = 1UL << mq->order;
  142. mq->mmr_blade = uv_cpu_to_blade_id(cpu);
  143. nid = cpu_to_node(cpu);
  144. page = __alloc_pages_node(nid,
  145. GFP_KERNEL | __GFP_ZERO | __GFP_THISNODE,
  146. pg_order);
  147. if (page == NULL) {
  148. dev_err(xpc_part, "xpc_create_gru_mq_uv() failed to alloc %d "
  149. "bytes of memory on nid=%d for GRU mq\n", mq_size, nid);
  150. ret = -ENOMEM;
  151. goto out_2;
  152. }
  153. mq->address = page_address(page);
  154. /* enable generation of irq when GRU mq operation occurs to this mq */
  155. ret = xpc_gru_mq_watchlist_alloc_uv(mq);
  156. if (ret != 0)
  157. goto out_3;
  158. ret = xpc_get_gru_mq_irq_uv(mq, cpu, irq_name);
  159. if (ret != 0)
  160. goto out_4;
  161. ret = request_irq(mq->irq, irq_handler, 0, irq_name, NULL);
  162. if (ret != 0) {
  163. dev_err(xpc_part, "request_irq(irq=%d) returned error=%d\n",
  164. mq->irq, -ret);
  165. goto out_5;
  166. }
  167. nasid = UV_PNODE_TO_NASID(uv_cpu_to_pnode(cpu));
  168. mmr_value = (struct uv_IO_APIC_route_entry *)&mq->mmr_value;
  169. ret = gru_create_message_queue(mq->gru_mq_desc, mq->address, mq_size,
  170. nasid, mmr_value->vector, mmr_value->dest);
  171. if (ret != 0) {
  172. dev_err(xpc_part, "gru_create_message_queue() returned "
  173. "error=%d\n", ret);
  174. ret = -EINVAL;
  175. goto out_6;
  176. }
  177. /* allow other partitions to access this GRU mq */
  178. xp_ret = xp_expand_memprotect(xp_pa(mq->address), mq_size);
  179. if (xp_ret != xpSuccess) {
  180. ret = -EACCES;
  181. goto out_6;
  182. }
  183. return mq;
  184. /* something went wrong */
  185. out_6:
  186. free_irq(mq->irq, NULL);
  187. out_5:
  188. xpc_release_gru_mq_irq_uv(mq);
  189. out_4:
  190. xpc_gru_mq_watchlist_free_uv(mq);
  191. out_3:
  192. free_pages((unsigned long)mq->address, pg_order);
  193. out_2:
  194. kfree(mq->gru_mq_desc);
  195. out_1:
  196. kfree(mq);
  197. out_0:
  198. return ERR_PTR(ret);
  199. }
  200. static void
  201. xpc_destroy_gru_mq_uv(struct xpc_gru_mq_uv *mq)
  202. {
  203. unsigned int mq_size;
  204. int pg_order;
  205. int ret;
  206. /* disallow other partitions to access GRU mq */
  207. mq_size = 1UL << mq->order;
  208. ret = xp_restrict_memprotect(xp_pa(mq->address), mq_size);
  209. BUG_ON(ret != xpSuccess);
  210. /* unregister irq handler and release mq irq/vector mapping */
  211. free_irq(mq->irq, NULL);
  212. xpc_release_gru_mq_irq_uv(mq);
  213. /* disable generation of irq when GRU mq op occurs to this mq */
  214. xpc_gru_mq_watchlist_free_uv(mq);
  215. pg_order = mq->order - PAGE_SHIFT;
  216. free_pages((unsigned long)mq->address, pg_order);
  217. kfree(mq);
  218. }
  219. static enum xp_retval
  220. xpc_send_gru_msg(struct gru_message_queue_desc *gru_mq_desc, void *msg,
  221. size_t msg_size)
  222. {
  223. enum xp_retval xp_ret;
  224. int ret;
  225. while (1) {
  226. ret = gru_send_message_gpa(gru_mq_desc, msg, msg_size);
  227. if (ret == MQE_OK) {
  228. xp_ret = xpSuccess;
  229. break;
  230. }
  231. if (ret == MQE_QUEUE_FULL) {
  232. dev_dbg(xpc_chan, "gru_send_message_gpa() returned "
  233. "error=MQE_QUEUE_FULL\n");
  234. /* !!! handle QLimit reached; delay & try again */
  235. /* ??? Do we add a limit to the number of retries? */
  236. (void)msleep_interruptible(10);
  237. } else if (ret == MQE_CONGESTION) {
  238. dev_dbg(xpc_chan, "gru_send_message_gpa() returned "
  239. "error=MQE_CONGESTION\n");
  240. /* !!! handle LB Overflow; simply try again */
  241. /* ??? Do we add a limit to the number of retries? */
  242. } else {
  243. /* !!! Currently this is MQE_UNEXPECTED_CB_ERR */
  244. dev_err(xpc_chan, "gru_send_message_gpa() returned "
  245. "error=%d\n", ret);
  246. xp_ret = xpGruSendMqError;
  247. break;
  248. }
  249. }
  250. return xp_ret;
  251. }
  252. static void
  253. xpc_process_activate_IRQ_rcvd_uv(void)
  254. {
  255. unsigned long irq_flags;
  256. short partid;
  257. struct xpc_partition *part;
  258. u8 act_state_req;
  259. DBUG_ON(xpc_activate_IRQ_rcvd == 0);
  260. spin_lock_irqsave(&xpc_activate_IRQ_rcvd_lock, irq_flags);
  261. for (partid = 0; partid < XP_MAX_NPARTITIONS_UV; partid++) {
  262. part = &xpc_partitions[partid];
  263. if (part->sn.uv.act_state_req == 0)
  264. continue;
  265. xpc_activate_IRQ_rcvd--;
  266. BUG_ON(xpc_activate_IRQ_rcvd < 0);
  267. act_state_req = part->sn.uv.act_state_req;
  268. part->sn.uv.act_state_req = 0;
  269. spin_unlock_irqrestore(&xpc_activate_IRQ_rcvd_lock, irq_flags);
  270. if (act_state_req == XPC_P_ASR_ACTIVATE_UV) {
  271. if (part->act_state == XPC_P_AS_INACTIVE)
  272. xpc_activate_partition(part);
  273. else if (part->act_state == XPC_P_AS_DEACTIVATING)
  274. XPC_DEACTIVATE_PARTITION(part, xpReactivating);
  275. } else if (act_state_req == XPC_P_ASR_REACTIVATE_UV) {
  276. if (part->act_state == XPC_P_AS_INACTIVE)
  277. xpc_activate_partition(part);
  278. else
  279. XPC_DEACTIVATE_PARTITION(part, xpReactivating);
  280. } else if (act_state_req == XPC_P_ASR_DEACTIVATE_UV) {
  281. XPC_DEACTIVATE_PARTITION(part, part->sn.uv.reason);
  282. } else {
  283. BUG();
  284. }
  285. spin_lock_irqsave(&xpc_activate_IRQ_rcvd_lock, irq_flags);
  286. if (xpc_activate_IRQ_rcvd == 0)
  287. break;
  288. }
  289. spin_unlock_irqrestore(&xpc_activate_IRQ_rcvd_lock, irq_flags);
  290. }
  291. static void
  292. xpc_handle_activate_mq_msg_uv(struct xpc_partition *part,
  293. struct xpc_activate_mq_msghdr_uv *msg_hdr,
  294. int part_setup,
  295. int *wakeup_hb_checker)
  296. {
  297. unsigned long irq_flags;
  298. struct xpc_partition_uv *part_uv = &part->sn.uv;
  299. struct xpc_openclose_args *args;
  300. part_uv->remote_act_state = msg_hdr->act_state;
  301. switch (msg_hdr->type) {
  302. case XPC_ACTIVATE_MQ_MSG_SYNC_ACT_STATE_UV:
  303. /* syncing of remote_act_state was just done above */
  304. break;
  305. case XPC_ACTIVATE_MQ_MSG_ACTIVATE_REQ_UV: {
  306. struct xpc_activate_mq_msg_activate_req_uv *msg;
  307. /*
  308. * ??? Do we deal here with ts_jiffies being different
  309. * ??? if act_state != XPC_P_AS_INACTIVE instead of
  310. * ??? below?
  311. */
  312. msg = container_of(msg_hdr, struct
  313. xpc_activate_mq_msg_activate_req_uv, hdr);
  314. spin_lock_irqsave(&xpc_activate_IRQ_rcvd_lock, irq_flags);
  315. if (part_uv->act_state_req == 0)
  316. xpc_activate_IRQ_rcvd++;
  317. part_uv->act_state_req = XPC_P_ASR_ACTIVATE_UV;
  318. part->remote_rp_pa = msg->rp_gpa; /* !!! _pa is _gpa */
  319. part->remote_rp_ts_jiffies = msg_hdr->rp_ts_jiffies;
  320. part_uv->heartbeat_gpa = msg->heartbeat_gpa;
  321. if (msg->activate_gru_mq_desc_gpa !=
  322. part_uv->activate_gru_mq_desc_gpa) {
  323. spin_lock(&part_uv->flags_lock);
  324. part_uv->flags &= ~XPC_P_CACHED_ACTIVATE_GRU_MQ_DESC_UV;
  325. spin_unlock(&part_uv->flags_lock);
  326. part_uv->activate_gru_mq_desc_gpa =
  327. msg->activate_gru_mq_desc_gpa;
  328. }
  329. spin_unlock_irqrestore(&xpc_activate_IRQ_rcvd_lock, irq_flags);
  330. (*wakeup_hb_checker)++;
  331. break;
  332. }
  333. case XPC_ACTIVATE_MQ_MSG_DEACTIVATE_REQ_UV: {
  334. struct xpc_activate_mq_msg_deactivate_req_uv *msg;
  335. msg = container_of(msg_hdr, struct
  336. xpc_activate_mq_msg_deactivate_req_uv, hdr);
  337. spin_lock_irqsave(&xpc_activate_IRQ_rcvd_lock, irq_flags);
  338. if (part_uv->act_state_req == 0)
  339. xpc_activate_IRQ_rcvd++;
  340. part_uv->act_state_req = XPC_P_ASR_DEACTIVATE_UV;
  341. part_uv->reason = msg->reason;
  342. spin_unlock_irqrestore(&xpc_activate_IRQ_rcvd_lock, irq_flags);
  343. (*wakeup_hb_checker)++;
  344. return;
  345. }
  346. case XPC_ACTIVATE_MQ_MSG_CHCTL_CLOSEREQUEST_UV: {
  347. struct xpc_activate_mq_msg_chctl_closerequest_uv *msg;
  348. if (!part_setup)
  349. break;
  350. msg = container_of(msg_hdr, struct
  351. xpc_activate_mq_msg_chctl_closerequest_uv,
  352. hdr);
  353. args = &part->remote_openclose_args[msg->ch_number];
  354. args->reason = msg->reason;
  355. spin_lock_irqsave(&part->chctl_lock, irq_flags);
  356. part->chctl.flags[msg->ch_number] |= XPC_CHCTL_CLOSEREQUEST;
  357. spin_unlock_irqrestore(&part->chctl_lock, irq_flags);
  358. xpc_wakeup_channel_mgr(part);
  359. break;
  360. }
  361. case XPC_ACTIVATE_MQ_MSG_CHCTL_CLOSEREPLY_UV: {
  362. struct xpc_activate_mq_msg_chctl_closereply_uv *msg;
  363. if (!part_setup)
  364. break;
  365. msg = container_of(msg_hdr, struct
  366. xpc_activate_mq_msg_chctl_closereply_uv,
  367. hdr);
  368. spin_lock_irqsave(&part->chctl_lock, irq_flags);
  369. part->chctl.flags[msg->ch_number] |= XPC_CHCTL_CLOSEREPLY;
  370. spin_unlock_irqrestore(&part->chctl_lock, irq_flags);
  371. xpc_wakeup_channel_mgr(part);
  372. break;
  373. }
  374. case XPC_ACTIVATE_MQ_MSG_CHCTL_OPENREQUEST_UV: {
  375. struct xpc_activate_mq_msg_chctl_openrequest_uv *msg;
  376. if (!part_setup)
  377. break;
  378. msg = container_of(msg_hdr, struct
  379. xpc_activate_mq_msg_chctl_openrequest_uv,
  380. hdr);
  381. args = &part->remote_openclose_args[msg->ch_number];
  382. args->entry_size = msg->entry_size;
  383. args->local_nentries = msg->local_nentries;
  384. spin_lock_irqsave(&part->chctl_lock, irq_flags);
  385. part->chctl.flags[msg->ch_number] |= XPC_CHCTL_OPENREQUEST;
  386. spin_unlock_irqrestore(&part->chctl_lock, irq_flags);
  387. xpc_wakeup_channel_mgr(part);
  388. break;
  389. }
  390. case XPC_ACTIVATE_MQ_MSG_CHCTL_OPENREPLY_UV: {
  391. struct xpc_activate_mq_msg_chctl_openreply_uv *msg;
  392. if (!part_setup)
  393. break;
  394. msg = container_of(msg_hdr, struct
  395. xpc_activate_mq_msg_chctl_openreply_uv, hdr);
  396. args = &part->remote_openclose_args[msg->ch_number];
  397. args->remote_nentries = msg->remote_nentries;
  398. args->local_nentries = msg->local_nentries;
  399. args->local_msgqueue_pa = msg->notify_gru_mq_desc_gpa;
  400. spin_lock_irqsave(&part->chctl_lock, irq_flags);
  401. part->chctl.flags[msg->ch_number] |= XPC_CHCTL_OPENREPLY;
  402. spin_unlock_irqrestore(&part->chctl_lock, irq_flags);
  403. xpc_wakeup_channel_mgr(part);
  404. break;
  405. }
  406. case XPC_ACTIVATE_MQ_MSG_CHCTL_OPENCOMPLETE_UV: {
  407. struct xpc_activate_mq_msg_chctl_opencomplete_uv *msg;
  408. if (!part_setup)
  409. break;
  410. msg = container_of(msg_hdr, struct
  411. xpc_activate_mq_msg_chctl_opencomplete_uv, hdr);
  412. spin_lock_irqsave(&part->chctl_lock, irq_flags);
  413. part->chctl.flags[msg->ch_number] |= XPC_CHCTL_OPENCOMPLETE;
  414. spin_unlock_irqrestore(&part->chctl_lock, irq_flags);
  415. xpc_wakeup_channel_mgr(part);
  416. }
  417. fallthrough;
  418. case XPC_ACTIVATE_MQ_MSG_MARK_ENGAGED_UV:
  419. spin_lock_irqsave(&part_uv->flags_lock, irq_flags);
  420. part_uv->flags |= XPC_P_ENGAGED_UV;
  421. spin_unlock_irqrestore(&part_uv->flags_lock, irq_flags);
  422. break;
  423. case XPC_ACTIVATE_MQ_MSG_MARK_DISENGAGED_UV:
  424. spin_lock_irqsave(&part_uv->flags_lock, irq_flags);
  425. part_uv->flags &= ~XPC_P_ENGAGED_UV;
  426. spin_unlock_irqrestore(&part_uv->flags_lock, irq_flags);
  427. break;
  428. default:
  429. dev_err(xpc_part, "received unknown activate_mq msg type=%d "
  430. "from partition=%d\n", msg_hdr->type, XPC_PARTID(part));
  431. /* get hb checker to deactivate from the remote partition */
  432. spin_lock_irqsave(&xpc_activate_IRQ_rcvd_lock, irq_flags);
  433. if (part_uv->act_state_req == 0)
  434. xpc_activate_IRQ_rcvd++;
  435. part_uv->act_state_req = XPC_P_ASR_DEACTIVATE_UV;
  436. part_uv->reason = xpBadMsgType;
  437. spin_unlock_irqrestore(&xpc_activate_IRQ_rcvd_lock, irq_flags);
  438. (*wakeup_hb_checker)++;
  439. return;
  440. }
  441. if (msg_hdr->rp_ts_jiffies != part->remote_rp_ts_jiffies &&
  442. part->remote_rp_ts_jiffies != 0) {
  443. /*
  444. * ??? Does what we do here need to be sensitive to
  445. * ??? act_state or remote_act_state?
  446. */
  447. spin_lock_irqsave(&xpc_activate_IRQ_rcvd_lock, irq_flags);
  448. if (part_uv->act_state_req == 0)
  449. xpc_activate_IRQ_rcvd++;
  450. part_uv->act_state_req = XPC_P_ASR_REACTIVATE_UV;
  451. spin_unlock_irqrestore(&xpc_activate_IRQ_rcvd_lock, irq_flags);
  452. (*wakeup_hb_checker)++;
  453. }
  454. }
  455. static irqreturn_t
  456. xpc_handle_activate_IRQ_uv(int irq, void *dev_id)
  457. {
  458. struct xpc_activate_mq_msghdr_uv *msg_hdr;
  459. short partid;
  460. struct xpc_partition *part;
  461. int wakeup_hb_checker = 0;
  462. int part_referenced;
  463. while (1) {
  464. msg_hdr = gru_get_next_message(xpc_activate_mq_uv->gru_mq_desc);
  465. if (msg_hdr == NULL)
  466. break;
  467. partid = msg_hdr->partid;
  468. if (partid < 0 || partid >= XP_MAX_NPARTITIONS_UV) {
  469. dev_err(xpc_part, "xpc_handle_activate_IRQ_uv() "
  470. "received invalid partid=0x%x in message\n",
  471. partid);
  472. } else {
  473. part = &xpc_partitions[partid];
  474. part_referenced = xpc_part_ref(part);
  475. xpc_handle_activate_mq_msg_uv(part, msg_hdr,
  476. part_referenced,
  477. &wakeup_hb_checker);
  478. if (part_referenced)
  479. xpc_part_deref(part);
  480. }
  481. gru_free_message(xpc_activate_mq_uv->gru_mq_desc, msg_hdr);
  482. }
  483. if (wakeup_hb_checker)
  484. wake_up_interruptible(&xpc_activate_IRQ_wq);
  485. return IRQ_HANDLED;
  486. }
  487. static enum xp_retval
  488. xpc_cache_remote_gru_mq_desc_uv(struct gru_message_queue_desc *gru_mq_desc,
  489. unsigned long gru_mq_desc_gpa)
  490. {
  491. enum xp_retval ret;
  492. ret = xp_remote_memcpy(uv_gpa(gru_mq_desc), gru_mq_desc_gpa,
  493. sizeof(struct gru_message_queue_desc));
  494. if (ret == xpSuccess)
  495. gru_mq_desc->mq = NULL;
  496. return ret;
  497. }
  498. static enum xp_retval
  499. xpc_send_activate_IRQ_uv(struct xpc_partition *part, void *msg, size_t msg_size,
  500. int msg_type)
  501. {
  502. struct xpc_activate_mq_msghdr_uv *msg_hdr = msg;
  503. struct xpc_partition_uv *part_uv = &part->sn.uv;
  504. struct gru_message_queue_desc *gru_mq_desc;
  505. unsigned long irq_flags;
  506. enum xp_retval ret;
  507. DBUG_ON(msg_size > XPC_ACTIVATE_MSG_SIZE_UV);
  508. msg_hdr->type = msg_type;
  509. msg_hdr->partid = xp_partition_id;
  510. msg_hdr->act_state = part->act_state;
  511. msg_hdr->rp_ts_jiffies = xpc_rsvd_page->ts_jiffies;
  512. mutex_lock(&part_uv->cached_activate_gru_mq_desc_mutex);
  513. again:
  514. if (!(part_uv->flags & XPC_P_CACHED_ACTIVATE_GRU_MQ_DESC_UV)) {
  515. gru_mq_desc = part_uv->cached_activate_gru_mq_desc;
  516. if (gru_mq_desc == NULL) {
  517. gru_mq_desc = kmalloc_obj(struct gru_message_queue_desc,
  518. GFP_ATOMIC);
  519. if (gru_mq_desc == NULL) {
  520. ret = xpNoMemory;
  521. goto done;
  522. }
  523. part_uv->cached_activate_gru_mq_desc = gru_mq_desc;
  524. }
  525. ret = xpc_cache_remote_gru_mq_desc_uv(gru_mq_desc,
  526. part_uv->
  527. activate_gru_mq_desc_gpa);
  528. if (ret != xpSuccess)
  529. goto done;
  530. spin_lock_irqsave(&part_uv->flags_lock, irq_flags);
  531. part_uv->flags |= XPC_P_CACHED_ACTIVATE_GRU_MQ_DESC_UV;
  532. spin_unlock_irqrestore(&part_uv->flags_lock, irq_flags);
  533. }
  534. /* ??? Is holding a spin_lock (ch->lock) during this call a bad idea? */
  535. ret = xpc_send_gru_msg(part_uv->cached_activate_gru_mq_desc, msg,
  536. msg_size);
  537. if (ret != xpSuccess) {
  538. smp_rmb(); /* ensure a fresh copy of part_uv->flags */
  539. if (!(part_uv->flags & XPC_P_CACHED_ACTIVATE_GRU_MQ_DESC_UV))
  540. goto again;
  541. }
  542. done:
  543. mutex_unlock(&part_uv->cached_activate_gru_mq_desc_mutex);
  544. return ret;
  545. }
  546. static void
  547. xpc_send_activate_IRQ_part_uv(struct xpc_partition *part, void *msg,
  548. size_t msg_size, int msg_type)
  549. {
  550. enum xp_retval ret;
  551. ret = xpc_send_activate_IRQ_uv(part, msg, msg_size, msg_type);
  552. if (unlikely(ret != xpSuccess))
  553. XPC_DEACTIVATE_PARTITION(part, ret);
  554. }
  555. static void
  556. xpc_send_activate_IRQ_ch_uv(struct xpc_channel *ch, unsigned long *irq_flags,
  557. void *msg, size_t msg_size, int msg_type)
  558. {
  559. struct xpc_partition *part = &xpc_partitions[ch->partid];
  560. enum xp_retval ret;
  561. ret = xpc_send_activate_IRQ_uv(part, msg, msg_size, msg_type);
  562. if (unlikely(ret != xpSuccess)) {
  563. if (irq_flags != NULL)
  564. spin_unlock_irqrestore(&ch->lock, *irq_flags);
  565. XPC_DEACTIVATE_PARTITION(part, ret);
  566. if (irq_flags != NULL)
  567. spin_lock_irqsave(&ch->lock, *irq_flags);
  568. }
  569. }
  570. static void
  571. xpc_send_local_activate_IRQ_uv(struct xpc_partition *part, int act_state_req)
  572. {
  573. unsigned long irq_flags;
  574. struct xpc_partition_uv *part_uv = &part->sn.uv;
  575. /*
  576. * !!! Make our side think that the remote partition sent an activate
  577. * !!! mq message our way by doing what the activate IRQ handler would
  578. * !!! do had one really been sent.
  579. */
  580. spin_lock_irqsave(&xpc_activate_IRQ_rcvd_lock, irq_flags);
  581. if (part_uv->act_state_req == 0)
  582. xpc_activate_IRQ_rcvd++;
  583. part_uv->act_state_req = act_state_req;
  584. spin_unlock_irqrestore(&xpc_activate_IRQ_rcvd_lock, irq_flags);
  585. wake_up_interruptible(&xpc_activate_IRQ_wq);
  586. }
  587. static enum xp_retval
  588. xpc_get_partition_rsvd_page_pa_uv(void *buf, u64 *cookie, unsigned long *rp_pa,
  589. size_t *len)
  590. {
  591. s64 status;
  592. enum xp_retval ret;
  593. status = uv_bios_reserved_page_pa((u64)buf, cookie, (u64 *)rp_pa,
  594. (u64 *)len);
  595. if (status == BIOS_STATUS_SUCCESS)
  596. ret = xpSuccess;
  597. else if (status == BIOS_STATUS_MORE_PASSES)
  598. ret = xpNeedMoreInfo;
  599. else
  600. ret = xpBiosError;
  601. return ret;
  602. }
  603. static int
  604. xpc_setup_rsvd_page_uv(struct xpc_rsvd_page *rp)
  605. {
  606. xpc_heartbeat_uv =
  607. &xpc_partitions[sn_partition_id].sn.uv.cached_heartbeat;
  608. rp->sn.uv.heartbeat_gpa = uv_gpa(xpc_heartbeat_uv);
  609. rp->sn.uv.activate_gru_mq_desc_gpa =
  610. uv_gpa(xpc_activate_mq_uv->gru_mq_desc);
  611. return 0;
  612. }
  613. static void
  614. xpc_allow_hb_uv(short partid)
  615. {
  616. }
  617. static void
  618. xpc_disallow_hb_uv(short partid)
  619. {
  620. }
  621. static void
  622. xpc_disallow_all_hbs_uv(void)
  623. {
  624. }
  625. static void
  626. xpc_increment_heartbeat_uv(void)
  627. {
  628. xpc_heartbeat_uv->value++;
  629. }
  630. static void
  631. xpc_offline_heartbeat_uv(void)
  632. {
  633. xpc_increment_heartbeat_uv();
  634. xpc_heartbeat_uv->offline = 1;
  635. }
  636. static void
  637. xpc_online_heartbeat_uv(void)
  638. {
  639. xpc_increment_heartbeat_uv();
  640. xpc_heartbeat_uv->offline = 0;
  641. }
  642. static void
  643. xpc_heartbeat_init_uv(void)
  644. {
  645. xpc_heartbeat_uv->value = 1;
  646. xpc_heartbeat_uv->offline = 0;
  647. }
  648. static void
  649. xpc_heartbeat_exit_uv(void)
  650. {
  651. xpc_offline_heartbeat_uv();
  652. }
  653. static enum xp_retval
  654. xpc_get_remote_heartbeat_uv(struct xpc_partition *part)
  655. {
  656. struct xpc_partition_uv *part_uv = &part->sn.uv;
  657. enum xp_retval ret;
  658. ret = xp_remote_memcpy(uv_gpa(&part_uv->cached_heartbeat),
  659. part_uv->heartbeat_gpa,
  660. sizeof(struct xpc_heartbeat_uv));
  661. if (ret != xpSuccess)
  662. return ret;
  663. if (part_uv->cached_heartbeat.value == part->last_heartbeat &&
  664. !part_uv->cached_heartbeat.offline) {
  665. ret = xpNoHeartbeat;
  666. } else {
  667. part->last_heartbeat = part_uv->cached_heartbeat.value;
  668. }
  669. return ret;
  670. }
  671. static void
  672. xpc_request_partition_activation_uv(struct xpc_rsvd_page *remote_rp,
  673. unsigned long remote_rp_gpa, int nasid)
  674. {
  675. short partid = remote_rp->SAL_partid;
  676. struct xpc_partition *part = &xpc_partitions[partid];
  677. struct xpc_activate_mq_msg_activate_req_uv msg;
  678. part->remote_rp_pa = remote_rp_gpa; /* !!! _pa here is really _gpa */
  679. part->remote_rp_ts_jiffies = remote_rp->ts_jiffies;
  680. part->sn.uv.heartbeat_gpa = remote_rp->sn.uv.heartbeat_gpa;
  681. part->sn.uv.activate_gru_mq_desc_gpa =
  682. remote_rp->sn.uv.activate_gru_mq_desc_gpa;
  683. /*
  684. * ??? Is it a good idea to make this conditional on what is
  685. * ??? potentially stale state information?
  686. */
  687. if (part->sn.uv.remote_act_state == XPC_P_AS_INACTIVE) {
  688. msg.rp_gpa = uv_gpa(xpc_rsvd_page);
  689. msg.heartbeat_gpa = xpc_rsvd_page->sn.uv.heartbeat_gpa;
  690. msg.activate_gru_mq_desc_gpa =
  691. xpc_rsvd_page->sn.uv.activate_gru_mq_desc_gpa;
  692. xpc_send_activate_IRQ_part_uv(part, &msg, sizeof(msg),
  693. XPC_ACTIVATE_MQ_MSG_ACTIVATE_REQ_UV);
  694. }
  695. if (part->act_state == XPC_P_AS_INACTIVE)
  696. xpc_send_local_activate_IRQ_uv(part, XPC_P_ASR_ACTIVATE_UV);
  697. }
  698. static void
  699. xpc_request_partition_reactivation_uv(struct xpc_partition *part)
  700. {
  701. xpc_send_local_activate_IRQ_uv(part, XPC_P_ASR_ACTIVATE_UV);
  702. }
  703. static void
  704. xpc_request_partition_deactivation_uv(struct xpc_partition *part)
  705. {
  706. struct xpc_activate_mq_msg_deactivate_req_uv msg;
  707. /*
  708. * ??? Is it a good idea to make this conditional on what is
  709. * ??? potentially stale state information?
  710. */
  711. if (part->sn.uv.remote_act_state != XPC_P_AS_DEACTIVATING &&
  712. part->sn.uv.remote_act_state != XPC_P_AS_INACTIVE) {
  713. msg.reason = part->reason;
  714. xpc_send_activate_IRQ_part_uv(part, &msg, sizeof(msg),
  715. XPC_ACTIVATE_MQ_MSG_DEACTIVATE_REQ_UV);
  716. }
  717. }
  718. static void
  719. xpc_cancel_partition_deactivation_request_uv(struct xpc_partition *part)
  720. {
  721. /* nothing needs to be done */
  722. return;
  723. }
  724. static void
  725. xpc_init_fifo_uv(struct xpc_fifo_head_uv *head)
  726. {
  727. head->first = NULL;
  728. head->last = NULL;
  729. spin_lock_init(&head->lock);
  730. head->n_entries = 0;
  731. }
  732. static void *
  733. xpc_get_fifo_entry_uv(struct xpc_fifo_head_uv *head)
  734. {
  735. unsigned long irq_flags;
  736. struct xpc_fifo_entry_uv *first;
  737. spin_lock_irqsave(&head->lock, irq_flags);
  738. first = head->first;
  739. if (head->first != NULL) {
  740. head->first = first->next;
  741. if (head->first == NULL)
  742. head->last = NULL;
  743. head->n_entries--;
  744. BUG_ON(head->n_entries < 0);
  745. first->next = NULL;
  746. }
  747. spin_unlock_irqrestore(&head->lock, irq_flags);
  748. return first;
  749. }
  750. static void
  751. xpc_put_fifo_entry_uv(struct xpc_fifo_head_uv *head,
  752. struct xpc_fifo_entry_uv *last)
  753. {
  754. unsigned long irq_flags;
  755. last->next = NULL;
  756. spin_lock_irqsave(&head->lock, irq_flags);
  757. if (head->last != NULL)
  758. head->last->next = last;
  759. else
  760. head->first = last;
  761. head->last = last;
  762. head->n_entries++;
  763. spin_unlock_irqrestore(&head->lock, irq_flags);
  764. }
  765. static int
  766. xpc_n_of_fifo_entries_uv(struct xpc_fifo_head_uv *head)
  767. {
  768. return head->n_entries;
  769. }
  770. /*
  771. * Setup the channel structures that are uv specific.
  772. */
  773. static enum xp_retval
  774. xpc_setup_ch_structures_uv(struct xpc_partition *part)
  775. {
  776. struct xpc_channel_uv *ch_uv;
  777. int ch_number;
  778. for (ch_number = 0; ch_number < part->nchannels; ch_number++) {
  779. ch_uv = &part->channels[ch_number].sn.uv;
  780. xpc_init_fifo_uv(&ch_uv->msg_slot_free_list);
  781. xpc_init_fifo_uv(&ch_uv->recv_msg_list);
  782. }
  783. return xpSuccess;
  784. }
  785. /*
  786. * Teardown the channel structures that are uv specific.
  787. */
  788. static void
  789. xpc_teardown_ch_structures_uv(struct xpc_partition *part)
  790. {
  791. /* nothing needs to be done */
  792. return;
  793. }
  794. static enum xp_retval
  795. xpc_make_first_contact_uv(struct xpc_partition *part)
  796. {
  797. struct xpc_activate_mq_msg_uv msg;
  798. /*
  799. * We send a sync msg to get the remote partition's remote_act_state
  800. * updated to our current act_state which at this point should
  801. * be XPC_P_AS_ACTIVATING.
  802. */
  803. xpc_send_activate_IRQ_part_uv(part, &msg, sizeof(msg),
  804. XPC_ACTIVATE_MQ_MSG_SYNC_ACT_STATE_UV);
  805. while (!((part->sn.uv.remote_act_state == XPC_P_AS_ACTIVATING) ||
  806. (part->sn.uv.remote_act_state == XPC_P_AS_ACTIVE))) {
  807. dev_dbg(xpc_part, "waiting to make first contact with "
  808. "partition %d\n", XPC_PARTID(part));
  809. /* wait a 1/4 of a second or so */
  810. (void)msleep_interruptible(250);
  811. if (part->act_state == XPC_P_AS_DEACTIVATING)
  812. return part->reason;
  813. }
  814. return xpSuccess;
  815. }
  816. static u64
  817. xpc_get_chctl_all_flags_uv(struct xpc_partition *part)
  818. {
  819. unsigned long irq_flags;
  820. union xpc_channel_ctl_flags chctl;
  821. spin_lock_irqsave(&part->chctl_lock, irq_flags);
  822. chctl = part->chctl;
  823. if (chctl.all_flags != 0)
  824. part->chctl.all_flags = 0;
  825. spin_unlock_irqrestore(&part->chctl_lock, irq_flags);
  826. return chctl.all_flags;
  827. }
  828. static enum xp_retval
  829. xpc_allocate_send_msg_slot_uv(struct xpc_channel *ch)
  830. {
  831. struct xpc_channel_uv *ch_uv = &ch->sn.uv;
  832. struct xpc_send_msg_slot_uv *msg_slot;
  833. unsigned long irq_flags;
  834. int nentries;
  835. int entry;
  836. size_t nbytes;
  837. for (nentries = ch->local_nentries; nentries > 0; nentries--) {
  838. nbytes = nentries * sizeof(struct xpc_send_msg_slot_uv);
  839. ch_uv->send_msg_slots = kzalloc(nbytes, GFP_KERNEL);
  840. if (ch_uv->send_msg_slots == NULL)
  841. continue;
  842. for (entry = 0; entry < nentries; entry++) {
  843. msg_slot = &ch_uv->send_msg_slots[entry];
  844. msg_slot->msg_slot_number = entry;
  845. xpc_put_fifo_entry_uv(&ch_uv->msg_slot_free_list,
  846. &msg_slot->next);
  847. }
  848. spin_lock_irqsave(&ch->lock, irq_flags);
  849. if (nentries < ch->local_nentries)
  850. ch->local_nentries = nentries;
  851. spin_unlock_irqrestore(&ch->lock, irq_flags);
  852. return xpSuccess;
  853. }
  854. return xpNoMemory;
  855. }
  856. static enum xp_retval
  857. xpc_allocate_recv_msg_slot_uv(struct xpc_channel *ch)
  858. {
  859. struct xpc_channel_uv *ch_uv = &ch->sn.uv;
  860. struct xpc_notify_mq_msg_uv *msg_slot;
  861. unsigned long irq_flags;
  862. int nentries;
  863. int entry;
  864. size_t nbytes;
  865. for (nentries = ch->remote_nentries; nentries > 0; nentries--) {
  866. nbytes = nentries * ch->entry_size;
  867. ch_uv->recv_msg_slots = kzalloc(nbytes, GFP_KERNEL);
  868. if (ch_uv->recv_msg_slots == NULL)
  869. continue;
  870. for (entry = 0; entry < nentries; entry++) {
  871. msg_slot = ch_uv->recv_msg_slots +
  872. entry * ch->entry_size;
  873. msg_slot->hdr.msg_slot_number = entry;
  874. }
  875. spin_lock_irqsave(&ch->lock, irq_flags);
  876. if (nentries < ch->remote_nentries)
  877. ch->remote_nentries = nentries;
  878. spin_unlock_irqrestore(&ch->lock, irq_flags);
  879. return xpSuccess;
  880. }
  881. return xpNoMemory;
  882. }
  883. /*
  884. * Allocate msg_slots associated with the channel.
  885. */
  886. static enum xp_retval
  887. xpc_setup_msg_structures_uv(struct xpc_channel *ch)
  888. {
  889. static enum xp_retval ret;
  890. struct xpc_channel_uv *ch_uv = &ch->sn.uv;
  891. DBUG_ON(ch->flags & XPC_C_SETUP);
  892. ch_uv->cached_notify_gru_mq_desc = kmalloc_obj(struct gru_message_queue_desc);
  893. if (ch_uv->cached_notify_gru_mq_desc == NULL)
  894. return xpNoMemory;
  895. ret = xpc_allocate_send_msg_slot_uv(ch);
  896. if (ret == xpSuccess) {
  897. ret = xpc_allocate_recv_msg_slot_uv(ch);
  898. if (ret != xpSuccess) {
  899. kfree(ch_uv->send_msg_slots);
  900. xpc_init_fifo_uv(&ch_uv->msg_slot_free_list);
  901. }
  902. }
  903. return ret;
  904. }
  905. /*
  906. * Free up msg_slots and clear other stuff that were setup for the specified
  907. * channel.
  908. */
  909. static void
  910. xpc_teardown_msg_structures_uv(struct xpc_channel *ch)
  911. {
  912. struct xpc_channel_uv *ch_uv = &ch->sn.uv;
  913. lockdep_assert_held(&ch->lock);
  914. kfree(ch_uv->cached_notify_gru_mq_desc);
  915. ch_uv->cached_notify_gru_mq_desc = NULL;
  916. if (ch->flags & XPC_C_SETUP) {
  917. xpc_init_fifo_uv(&ch_uv->msg_slot_free_list);
  918. kfree(ch_uv->send_msg_slots);
  919. xpc_init_fifo_uv(&ch_uv->recv_msg_list);
  920. kfree(ch_uv->recv_msg_slots);
  921. }
  922. }
  923. static void
  924. xpc_send_chctl_closerequest_uv(struct xpc_channel *ch, unsigned long *irq_flags)
  925. {
  926. struct xpc_activate_mq_msg_chctl_closerequest_uv msg;
  927. msg.ch_number = ch->number;
  928. msg.reason = ch->reason;
  929. xpc_send_activate_IRQ_ch_uv(ch, irq_flags, &msg, sizeof(msg),
  930. XPC_ACTIVATE_MQ_MSG_CHCTL_CLOSEREQUEST_UV);
  931. }
  932. static void
  933. xpc_send_chctl_closereply_uv(struct xpc_channel *ch, unsigned long *irq_flags)
  934. {
  935. struct xpc_activate_mq_msg_chctl_closereply_uv msg;
  936. msg.ch_number = ch->number;
  937. xpc_send_activate_IRQ_ch_uv(ch, irq_flags, &msg, sizeof(msg),
  938. XPC_ACTIVATE_MQ_MSG_CHCTL_CLOSEREPLY_UV);
  939. }
  940. static void
  941. xpc_send_chctl_openrequest_uv(struct xpc_channel *ch, unsigned long *irq_flags)
  942. {
  943. struct xpc_activate_mq_msg_chctl_openrequest_uv msg;
  944. msg.ch_number = ch->number;
  945. msg.entry_size = ch->entry_size;
  946. msg.local_nentries = ch->local_nentries;
  947. xpc_send_activate_IRQ_ch_uv(ch, irq_flags, &msg, sizeof(msg),
  948. XPC_ACTIVATE_MQ_MSG_CHCTL_OPENREQUEST_UV);
  949. }
  950. static void
  951. xpc_send_chctl_openreply_uv(struct xpc_channel *ch, unsigned long *irq_flags)
  952. {
  953. struct xpc_activate_mq_msg_chctl_openreply_uv msg;
  954. msg.ch_number = ch->number;
  955. msg.local_nentries = ch->local_nentries;
  956. msg.remote_nentries = ch->remote_nentries;
  957. msg.notify_gru_mq_desc_gpa = uv_gpa(xpc_notify_mq_uv->gru_mq_desc);
  958. xpc_send_activate_IRQ_ch_uv(ch, irq_flags, &msg, sizeof(msg),
  959. XPC_ACTIVATE_MQ_MSG_CHCTL_OPENREPLY_UV);
  960. }
  961. static void
  962. xpc_send_chctl_opencomplete_uv(struct xpc_channel *ch, unsigned long *irq_flags)
  963. {
  964. struct xpc_activate_mq_msg_chctl_opencomplete_uv msg;
  965. msg.ch_number = ch->number;
  966. xpc_send_activate_IRQ_ch_uv(ch, irq_flags, &msg, sizeof(msg),
  967. XPC_ACTIVATE_MQ_MSG_CHCTL_OPENCOMPLETE_UV);
  968. }
  969. static void
  970. xpc_send_chctl_local_msgrequest_uv(struct xpc_partition *part, int ch_number)
  971. {
  972. unsigned long irq_flags;
  973. spin_lock_irqsave(&part->chctl_lock, irq_flags);
  974. part->chctl.flags[ch_number] |= XPC_CHCTL_MSGREQUEST;
  975. spin_unlock_irqrestore(&part->chctl_lock, irq_flags);
  976. xpc_wakeup_channel_mgr(part);
  977. }
  978. static enum xp_retval
  979. xpc_save_remote_msgqueue_pa_uv(struct xpc_channel *ch,
  980. unsigned long gru_mq_desc_gpa)
  981. {
  982. struct xpc_channel_uv *ch_uv = &ch->sn.uv;
  983. DBUG_ON(ch_uv->cached_notify_gru_mq_desc == NULL);
  984. return xpc_cache_remote_gru_mq_desc_uv(ch_uv->cached_notify_gru_mq_desc,
  985. gru_mq_desc_gpa);
  986. }
  987. static void
  988. xpc_indicate_partition_engaged_uv(struct xpc_partition *part)
  989. {
  990. struct xpc_activate_mq_msg_uv msg;
  991. xpc_send_activate_IRQ_part_uv(part, &msg, sizeof(msg),
  992. XPC_ACTIVATE_MQ_MSG_MARK_ENGAGED_UV);
  993. }
  994. static void
  995. xpc_indicate_partition_disengaged_uv(struct xpc_partition *part)
  996. {
  997. struct xpc_activate_mq_msg_uv msg;
  998. xpc_send_activate_IRQ_part_uv(part, &msg, sizeof(msg),
  999. XPC_ACTIVATE_MQ_MSG_MARK_DISENGAGED_UV);
  1000. }
  1001. static void
  1002. xpc_assume_partition_disengaged_uv(short partid)
  1003. {
  1004. struct xpc_partition_uv *part_uv = &xpc_partitions[partid].sn.uv;
  1005. unsigned long irq_flags;
  1006. spin_lock_irqsave(&part_uv->flags_lock, irq_flags);
  1007. part_uv->flags &= ~XPC_P_ENGAGED_UV;
  1008. spin_unlock_irqrestore(&part_uv->flags_lock, irq_flags);
  1009. }
  1010. static int
  1011. xpc_partition_engaged_uv(short partid)
  1012. {
  1013. return (xpc_partitions[partid].sn.uv.flags & XPC_P_ENGAGED_UV) != 0;
  1014. }
  1015. static int
  1016. xpc_any_partition_engaged_uv(void)
  1017. {
  1018. struct xpc_partition_uv *part_uv;
  1019. short partid;
  1020. for (partid = 0; partid < XP_MAX_NPARTITIONS_UV; partid++) {
  1021. part_uv = &xpc_partitions[partid].sn.uv;
  1022. if ((part_uv->flags & XPC_P_ENGAGED_UV) != 0)
  1023. return 1;
  1024. }
  1025. return 0;
  1026. }
  1027. static enum xp_retval
  1028. xpc_allocate_msg_slot_uv(struct xpc_channel *ch, u32 flags,
  1029. struct xpc_send_msg_slot_uv **address_of_msg_slot)
  1030. {
  1031. enum xp_retval ret;
  1032. struct xpc_send_msg_slot_uv *msg_slot;
  1033. struct xpc_fifo_entry_uv *entry;
  1034. while (1) {
  1035. entry = xpc_get_fifo_entry_uv(&ch->sn.uv.msg_slot_free_list);
  1036. if (entry != NULL)
  1037. break;
  1038. if (flags & XPC_NOWAIT)
  1039. return xpNoWait;
  1040. ret = xpc_allocate_msg_wait(ch);
  1041. if (ret != xpInterrupted && ret != xpTimeout)
  1042. return ret;
  1043. }
  1044. msg_slot = container_of(entry, struct xpc_send_msg_slot_uv, next);
  1045. *address_of_msg_slot = msg_slot;
  1046. return xpSuccess;
  1047. }
  1048. static void
  1049. xpc_free_msg_slot_uv(struct xpc_channel *ch,
  1050. struct xpc_send_msg_slot_uv *msg_slot)
  1051. {
  1052. xpc_put_fifo_entry_uv(&ch->sn.uv.msg_slot_free_list, &msg_slot->next);
  1053. /* wakeup anyone waiting for a free msg slot */
  1054. if (atomic_read(&ch->n_on_msg_allocate_wq) > 0)
  1055. wake_up(&ch->msg_allocate_wq);
  1056. }
  1057. static void
  1058. xpc_notify_sender_uv(struct xpc_channel *ch,
  1059. struct xpc_send_msg_slot_uv *msg_slot,
  1060. enum xp_retval reason)
  1061. {
  1062. xpc_notify_func func = msg_slot->func;
  1063. if (func != NULL && cmpxchg(&msg_slot->func, func, NULL) == func) {
  1064. atomic_dec(&ch->n_to_notify);
  1065. dev_dbg(xpc_chan, "msg_slot->func() called, msg_slot=0x%p "
  1066. "msg_slot_number=%d partid=%d channel=%d\n", msg_slot,
  1067. msg_slot->msg_slot_number, ch->partid, ch->number);
  1068. func(reason, ch->partid, ch->number, msg_slot->key);
  1069. dev_dbg(xpc_chan, "msg_slot->func() returned, msg_slot=0x%p "
  1070. "msg_slot_number=%d partid=%d channel=%d\n", msg_slot,
  1071. msg_slot->msg_slot_number, ch->partid, ch->number);
  1072. }
  1073. }
  1074. static void
  1075. xpc_handle_notify_mq_ack_uv(struct xpc_channel *ch,
  1076. struct xpc_notify_mq_msg_uv *msg)
  1077. {
  1078. struct xpc_send_msg_slot_uv *msg_slot;
  1079. int entry = msg->hdr.msg_slot_number % ch->local_nentries;
  1080. msg_slot = &ch->sn.uv.send_msg_slots[entry];
  1081. BUG_ON(msg_slot->msg_slot_number != msg->hdr.msg_slot_number);
  1082. msg_slot->msg_slot_number += ch->local_nentries;
  1083. if (msg_slot->func != NULL)
  1084. xpc_notify_sender_uv(ch, msg_slot, xpMsgDelivered);
  1085. xpc_free_msg_slot_uv(ch, msg_slot);
  1086. }
  1087. static void
  1088. xpc_handle_notify_mq_msg_uv(struct xpc_partition *part,
  1089. struct xpc_notify_mq_msg_uv *msg)
  1090. {
  1091. struct xpc_partition_uv *part_uv = &part->sn.uv;
  1092. struct xpc_channel *ch;
  1093. struct xpc_channel_uv *ch_uv;
  1094. struct xpc_notify_mq_msg_uv *msg_slot;
  1095. unsigned long irq_flags;
  1096. int ch_number = msg->hdr.ch_number;
  1097. if (unlikely(ch_number >= part->nchannels)) {
  1098. dev_err(xpc_part, "xpc_handle_notify_IRQ_uv() received invalid "
  1099. "channel number=0x%x in message from partid=%d\n",
  1100. ch_number, XPC_PARTID(part));
  1101. /* get hb checker to deactivate from the remote partition */
  1102. spin_lock_irqsave(&xpc_activate_IRQ_rcvd_lock, irq_flags);
  1103. if (part_uv->act_state_req == 0)
  1104. xpc_activate_IRQ_rcvd++;
  1105. part_uv->act_state_req = XPC_P_ASR_DEACTIVATE_UV;
  1106. part_uv->reason = xpBadChannelNumber;
  1107. spin_unlock_irqrestore(&xpc_activate_IRQ_rcvd_lock, irq_flags);
  1108. wake_up_interruptible(&xpc_activate_IRQ_wq);
  1109. return;
  1110. }
  1111. ch = &part->channels[ch_number];
  1112. xpc_msgqueue_ref(ch);
  1113. if (!(ch->flags & XPC_C_CONNECTED)) {
  1114. xpc_msgqueue_deref(ch);
  1115. return;
  1116. }
  1117. /* see if we're really dealing with an ACK for a previously sent msg */
  1118. if (msg->hdr.size == 0) {
  1119. xpc_handle_notify_mq_ack_uv(ch, msg);
  1120. xpc_msgqueue_deref(ch);
  1121. return;
  1122. }
  1123. /* we're dealing with a normal message sent via the notify_mq */
  1124. ch_uv = &ch->sn.uv;
  1125. msg_slot = ch_uv->recv_msg_slots +
  1126. (msg->hdr.msg_slot_number % ch->remote_nentries) * ch->entry_size;
  1127. BUG_ON(msg_slot->hdr.size != 0);
  1128. memcpy(msg_slot, msg, msg->hdr.size);
  1129. xpc_put_fifo_entry_uv(&ch_uv->recv_msg_list, &msg_slot->hdr.u.next);
  1130. if (ch->flags & XPC_C_CONNECTEDCALLOUT_MADE) {
  1131. /*
  1132. * If there is an existing idle kthread get it to deliver
  1133. * the payload, otherwise we'll have to get the channel mgr
  1134. * for this partition to create a kthread to do the delivery.
  1135. */
  1136. if (atomic_read(&ch->kthreads_idle) > 0)
  1137. wake_up_nr(&ch->idle_wq, 1);
  1138. else
  1139. xpc_send_chctl_local_msgrequest_uv(part, ch->number);
  1140. }
  1141. xpc_msgqueue_deref(ch);
  1142. }
  1143. static irqreturn_t
  1144. xpc_handle_notify_IRQ_uv(int irq, void *dev_id)
  1145. {
  1146. struct xpc_notify_mq_msg_uv *msg;
  1147. short partid;
  1148. struct xpc_partition *part;
  1149. while ((msg = gru_get_next_message(xpc_notify_mq_uv->gru_mq_desc)) !=
  1150. NULL) {
  1151. partid = msg->hdr.partid;
  1152. if (partid < 0 || partid >= XP_MAX_NPARTITIONS_UV) {
  1153. dev_err(xpc_part, "xpc_handle_notify_IRQ_uv() received "
  1154. "invalid partid=0x%x in message\n", partid);
  1155. } else {
  1156. part = &xpc_partitions[partid];
  1157. if (xpc_part_ref(part)) {
  1158. xpc_handle_notify_mq_msg_uv(part, msg);
  1159. xpc_part_deref(part);
  1160. }
  1161. }
  1162. gru_free_message(xpc_notify_mq_uv->gru_mq_desc, msg);
  1163. }
  1164. return IRQ_HANDLED;
  1165. }
  1166. static int
  1167. xpc_n_of_deliverable_payloads_uv(struct xpc_channel *ch)
  1168. {
  1169. return xpc_n_of_fifo_entries_uv(&ch->sn.uv.recv_msg_list);
  1170. }
  1171. static void
  1172. xpc_process_msg_chctl_flags_uv(struct xpc_partition *part, int ch_number)
  1173. {
  1174. struct xpc_channel *ch = &part->channels[ch_number];
  1175. int ndeliverable_payloads;
  1176. xpc_msgqueue_ref(ch);
  1177. ndeliverable_payloads = xpc_n_of_deliverable_payloads_uv(ch);
  1178. if (ndeliverable_payloads > 0 &&
  1179. (ch->flags & XPC_C_CONNECTED) &&
  1180. (ch->flags & XPC_C_CONNECTEDCALLOUT_MADE)) {
  1181. xpc_activate_kthreads(ch, ndeliverable_payloads);
  1182. }
  1183. xpc_msgqueue_deref(ch);
  1184. }
  1185. static enum xp_retval
  1186. xpc_send_payload_uv(struct xpc_channel *ch, u32 flags, void *payload,
  1187. u16 payload_size, u8 notify_type, xpc_notify_func func,
  1188. void *key)
  1189. {
  1190. enum xp_retval ret = xpSuccess;
  1191. struct xpc_send_msg_slot_uv *msg_slot = NULL;
  1192. struct xpc_notify_mq_msg_uv *msg;
  1193. u8 msg_buffer[XPC_NOTIFY_MSG_SIZE_UV];
  1194. size_t msg_size;
  1195. DBUG_ON(notify_type != XPC_N_CALL);
  1196. msg_size = sizeof(struct xpc_notify_mq_msghdr_uv) + payload_size;
  1197. if (msg_size > ch->entry_size)
  1198. return xpPayloadTooBig;
  1199. xpc_msgqueue_ref(ch);
  1200. if (ch->flags & XPC_C_DISCONNECTING) {
  1201. ret = ch->reason;
  1202. goto out_1;
  1203. }
  1204. if (!(ch->flags & XPC_C_CONNECTED)) {
  1205. ret = xpNotConnected;
  1206. goto out_1;
  1207. }
  1208. ret = xpc_allocate_msg_slot_uv(ch, flags, &msg_slot);
  1209. if (ret != xpSuccess)
  1210. goto out_1;
  1211. if (func != NULL) {
  1212. atomic_inc(&ch->n_to_notify);
  1213. msg_slot->key = key;
  1214. smp_wmb(); /* a non-NULL func must hit memory after the key */
  1215. msg_slot->func = func;
  1216. if (ch->flags & XPC_C_DISCONNECTING) {
  1217. ret = ch->reason;
  1218. goto out_2;
  1219. }
  1220. }
  1221. msg = (struct xpc_notify_mq_msg_uv *)&msg_buffer;
  1222. msg->hdr.partid = xp_partition_id;
  1223. msg->hdr.ch_number = ch->number;
  1224. msg->hdr.size = msg_size;
  1225. msg->hdr.msg_slot_number = msg_slot->msg_slot_number;
  1226. memcpy(&msg->payload, payload, payload_size);
  1227. ret = xpc_send_gru_msg(ch->sn.uv.cached_notify_gru_mq_desc, msg,
  1228. msg_size);
  1229. if (ret == xpSuccess)
  1230. goto out_1;
  1231. XPC_DEACTIVATE_PARTITION(&xpc_partitions[ch->partid], ret);
  1232. out_2:
  1233. if (func != NULL) {
  1234. /*
  1235. * Try to NULL the msg_slot's func field. If we fail, then
  1236. * xpc_notify_senders_of_disconnect_uv() beat us to it, in which
  1237. * case we need to pretend we succeeded to send the message
  1238. * since the user will get a callout for the disconnect error
  1239. * by xpc_notify_senders_of_disconnect_uv(), and to also get an
  1240. * error returned here will confuse them. Additionally, since
  1241. * in this case the channel is being disconnected we don't need
  1242. * to put the msg_slot back on the free list.
  1243. */
  1244. if (cmpxchg(&msg_slot->func, func, NULL) != func) {
  1245. ret = xpSuccess;
  1246. goto out_1;
  1247. }
  1248. msg_slot->key = NULL;
  1249. atomic_dec(&ch->n_to_notify);
  1250. }
  1251. xpc_free_msg_slot_uv(ch, msg_slot);
  1252. out_1:
  1253. xpc_msgqueue_deref(ch);
  1254. return ret;
  1255. }
  1256. /*
  1257. * Tell the callers of xpc_send_notify() that the status of their payloads
  1258. * is unknown because the channel is now disconnecting.
  1259. *
  1260. * We don't worry about putting these msg_slots on the free list since the
  1261. * msg_slots themselves are about to be kfree'd.
  1262. */
  1263. static void
  1264. xpc_notify_senders_of_disconnect_uv(struct xpc_channel *ch)
  1265. {
  1266. struct xpc_send_msg_slot_uv *msg_slot;
  1267. int entry;
  1268. DBUG_ON(!(ch->flags & XPC_C_DISCONNECTING));
  1269. for (entry = 0; entry < ch->local_nentries; entry++) {
  1270. if (atomic_read(&ch->n_to_notify) == 0)
  1271. break;
  1272. msg_slot = &ch->sn.uv.send_msg_slots[entry];
  1273. if (msg_slot->func != NULL)
  1274. xpc_notify_sender_uv(ch, msg_slot, ch->reason);
  1275. }
  1276. }
  1277. /*
  1278. * Get the next deliverable message's payload.
  1279. */
  1280. static void *
  1281. xpc_get_deliverable_payload_uv(struct xpc_channel *ch)
  1282. {
  1283. struct xpc_fifo_entry_uv *entry;
  1284. struct xpc_notify_mq_msg_uv *msg;
  1285. void *payload = NULL;
  1286. if (!(ch->flags & XPC_C_DISCONNECTING)) {
  1287. entry = xpc_get_fifo_entry_uv(&ch->sn.uv.recv_msg_list);
  1288. if (entry != NULL) {
  1289. msg = container_of(entry, struct xpc_notify_mq_msg_uv,
  1290. hdr.u.next);
  1291. payload = &msg->payload;
  1292. }
  1293. }
  1294. return payload;
  1295. }
  1296. static void
  1297. xpc_received_payload_uv(struct xpc_channel *ch, void *payload)
  1298. {
  1299. struct xpc_notify_mq_msg_uv *msg;
  1300. enum xp_retval ret;
  1301. msg = container_of(payload, struct xpc_notify_mq_msg_uv, payload);
  1302. /* return an ACK to the sender of this message */
  1303. msg->hdr.partid = xp_partition_id;
  1304. msg->hdr.size = 0; /* size of zero indicates this is an ACK */
  1305. ret = xpc_send_gru_msg(ch->sn.uv.cached_notify_gru_mq_desc, msg,
  1306. sizeof(struct xpc_notify_mq_msghdr_uv));
  1307. if (ret != xpSuccess)
  1308. XPC_DEACTIVATE_PARTITION(&xpc_partitions[ch->partid], ret);
  1309. }
  1310. static const struct xpc_arch_operations xpc_arch_ops_uv = {
  1311. .setup_partitions = xpc_setup_partitions_uv,
  1312. .teardown_partitions = xpc_teardown_partitions_uv,
  1313. .process_activate_IRQ_rcvd = xpc_process_activate_IRQ_rcvd_uv,
  1314. .get_partition_rsvd_page_pa = xpc_get_partition_rsvd_page_pa_uv,
  1315. .setup_rsvd_page = xpc_setup_rsvd_page_uv,
  1316. .allow_hb = xpc_allow_hb_uv,
  1317. .disallow_hb = xpc_disallow_hb_uv,
  1318. .disallow_all_hbs = xpc_disallow_all_hbs_uv,
  1319. .increment_heartbeat = xpc_increment_heartbeat_uv,
  1320. .offline_heartbeat = xpc_offline_heartbeat_uv,
  1321. .online_heartbeat = xpc_online_heartbeat_uv,
  1322. .heartbeat_init = xpc_heartbeat_init_uv,
  1323. .heartbeat_exit = xpc_heartbeat_exit_uv,
  1324. .get_remote_heartbeat = xpc_get_remote_heartbeat_uv,
  1325. .request_partition_activation =
  1326. xpc_request_partition_activation_uv,
  1327. .request_partition_reactivation =
  1328. xpc_request_partition_reactivation_uv,
  1329. .request_partition_deactivation =
  1330. xpc_request_partition_deactivation_uv,
  1331. .cancel_partition_deactivation_request =
  1332. xpc_cancel_partition_deactivation_request_uv,
  1333. .setup_ch_structures = xpc_setup_ch_structures_uv,
  1334. .teardown_ch_structures = xpc_teardown_ch_structures_uv,
  1335. .make_first_contact = xpc_make_first_contact_uv,
  1336. .get_chctl_all_flags = xpc_get_chctl_all_flags_uv,
  1337. .send_chctl_closerequest = xpc_send_chctl_closerequest_uv,
  1338. .send_chctl_closereply = xpc_send_chctl_closereply_uv,
  1339. .send_chctl_openrequest = xpc_send_chctl_openrequest_uv,
  1340. .send_chctl_openreply = xpc_send_chctl_openreply_uv,
  1341. .send_chctl_opencomplete = xpc_send_chctl_opencomplete_uv,
  1342. .process_msg_chctl_flags = xpc_process_msg_chctl_flags_uv,
  1343. .save_remote_msgqueue_pa = xpc_save_remote_msgqueue_pa_uv,
  1344. .setup_msg_structures = xpc_setup_msg_structures_uv,
  1345. .teardown_msg_structures = xpc_teardown_msg_structures_uv,
  1346. .indicate_partition_engaged = xpc_indicate_partition_engaged_uv,
  1347. .indicate_partition_disengaged = xpc_indicate_partition_disengaged_uv,
  1348. .assume_partition_disengaged = xpc_assume_partition_disengaged_uv,
  1349. .partition_engaged = xpc_partition_engaged_uv,
  1350. .any_partition_engaged = xpc_any_partition_engaged_uv,
  1351. .n_of_deliverable_payloads = xpc_n_of_deliverable_payloads_uv,
  1352. .send_payload = xpc_send_payload_uv,
  1353. .get_deliverable_payload = xpc_get_deliverable_payload_uv,
  1354. .received_payload = xpc_received_payload_uv,
  1355. .notify_senders_of_disconnect = xpc_notify_senders_of_disconnect_uv,
  1356. };
  1357. static int
  1358. xpc_init_mq_node(int nid)
  1359. {
  1360. int cpu;
  1361. cpus_read_lock();
  1362. for_each_cpu(cpu, cpumask_of_node(nid)) {
  1363. xpc_activate_mq_uv =
  1364. xpc_create_gru_mq_uv(XPC_ACTIVATE_MQ_SIZE_UV, nid,
  1365. XPC_ACTIVATE_IRQ_NAME,
  1366. xpc_handle_activate_IRQ_uv);
  1367. if (!IS_ERR(xpc_activate_mq_uv))
  1368. break;
  1369. }
  1370. if (IS_ERR(xpc_activate_mq_uv)) {
  1371. cpus_read_unlock();
  1372. return PTR_ERR(xpc_activate_mq_uv);
  1373. }
  1374. for_each_cpu(cpu, cpumask_of_node(nid)) {
  1375. xpc_notify_mq_uv =
  1376. xpc_create_gru_mq_uv(XPC_NOTIFY_MQ_SIZE_UV, nid,
  1377. XPC_NOTIFY_IRQ_NAME,
  1378. xpc_handle_notify_IRQ_uv);
  1379. if (!IS_ERR(xpc_notify_mq_uv))
  1380. break;
  1381. }
  1382. if (IS_ERR(xpc_notify_mq_uv)) {
  1383. xpc_destroy_gru_mq_uv(xpc_activate_mq_uv);
  1384. cpus_read_unlock();
  1385. return PTR_ERR(xpc_notify_mq_uv);
  1386. }
  1387. cpus_read_unlock();
  1388. return 0;
  1389. }
  1390. int
  1391. xpc_init_uv(void)
  1392. {
  1393. int nid;
  1394. int ret = 0;
  1395. xpc_arch_ops = xpc_arch_ops_uv;
  1396. if (sizeof(struct xpc_notify_mq_msghdr_uv) > XPC_MSG_HDR_MAX_SIZE) {
  1397. dev_err(xpc_part, "xpc_notify_mq_msghdr_uv is larger than %d\n",
  1398. XPC_MSG_HDR_MAX_SIZE);
  1399. return -E2BIG;
  1400. }
  1401. if (xpc_mq_node < 0)
  1402. for_each_online_node(nid) {
  1403. ret = xpc_init_mq_node(nid);
  1404. if (!ret)
  1405. break;
  1406. }
  1407. else
  1408. ret = xpc_init_mq_node(xpc_mq_node);
  1409. if (ret < 0)
  1410. dev_err(xpc_part, "xpc_init_mq_node() returned error=%d\n",
  1411. -ret);
  1412. return ret;
  1413. }
  1414. void
  1415. xpc_exit_uv(void)
  1416. {
  1417. xpc_destroy_gru_mq_uv(xpc_notify_mq_uv);
  1418. xpc_destroy_gru_mq_uv(xpc_activate_mq_uv);
  1419. }
  1420. module_param(xpc_mq_node, int, 0);
  1421. MODULE_PARM_DESC(xpc_mq_node, "Node number on which to allocate message queues.");