scif_nm.c 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  1. /*
  2. * Intel MIC Platform Software Stack (MPSS)
  3. *
  4. * Copyright(c) 2014 Intel Corporation.
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License, version 2, as
  8. * published by the Free Software Foundation.
  9. *
  10. * This program is distributed in the hope that it will be useful, but
  11. * WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  13. * General Public License for more details.
  14. *
  15. * Intel SCIF driver.
  16. *
  17. */
  18. #include "scif_peer_bus.h"
  19. #include "scif_main.h"
  20. #include "scif_map.h"
  21. /**
  22. * scif_invalidate_ep() - Set state for all connected endpoints
  23. * to disconnected and wake up all send/recv waitqueues
  24. */
  25. static void scif_invalidate_ep(int node)
  26. {
  27. struct scif_endpt *ep;
  28. struct list_head *pos, *tmpq;
  29. flush_work(&scif_info.conn_work);
  30. mutex_lock(&scif_info.connlock);
  31. list_for_each_safe(pos, tmpq, &scif_info.disconnected) {
  32. ep = list_entry(pos, struct scif_endpt, list);
  33. if (ep->remote_dev->node == node) {
  34. scif_unmap_all_windows(ep);
  35. spin_lock(&ep->lock);
  36. scif_cleanup_ep_qp(ep);
  37. spin_unlock(&ep->lock);
  38. }
  39. }
  40. list_for_each_safe(pos, tmpq, &scif_info.connected) {
  41. ep = list_entry(pos, struct scif_endpt, list);
  42. if (ep->remote_dev->node == node) {
  43. list_del(pos);
  44. spin_lock(&ep->lock);
  45. ep->state = SCIFEP_DISCONNECTED;
  46. list_add_tail(&ep->list, &scif_info.disconnected);
  47. scif_cleanup_ep_qp(ep);
  48. wake_up_interruptible(&ep->sendwq);
  49. wake_up_interruptible(&ep->recvwq);
  50. spin_unlock(&ep->lock);
  51. scif_unmap_all_windows(ep);
  52. }
  53. }
  54. mutex_unlock(&scif_info.connlock);
  55. }
  56. void scif_free_qp(struct scif_dev *scifdev)
  57. {
  58. struct scif_qp *qp = scifdev->qpairs;
  59. if (!qp)
  60. return;
  61. scif_unmap_single(qp->local_buf, scifdev, qp->inbound_q.size);
  62. kfree(qp->inbound_q.rb_base);
  63. scif_unmap_single(qp->local_qp, scifdev, sizeof(struct scif_qp));
  64. kfree(scifdev->qpairs);
  65. scifdev->qpairs = NULL;
  66. }
  67. static void scif_cleanup_qp(struct scif_dev *dev)
  68. {
  69. struct scif_qp *qp = &dev->qpairs[0];
  70. if (!qp)
  71. return;
  72. scif_iounmap((void *)qp->remote_qp, sizeof(struct scif_qp), dev);
  73. scif_iounmap((void *)qp->outbound_q.rb_base,
  74. sizeof(struct scif_qp), dev);
  75. qp->remote_qp = NULL;
  76. qp->local_write = 0;
  77. qp->inbound_q.current_write_offset = 0;
  78. qp->inbound_q.current_read_offset = 0;
  79. if (scifdev_is_p2p(dev))
  80. scif_free_qp(dev);
  81. }
  82. void scif_send_acks(struct scif_dev *dev)
  83. {
  84. struct scifmsg msg;
  85. if (dev->node_remove_ack_pending) {
  86. msg.uop = SCIF_NODE_REMOVE_ACK;
  87. msg.src.node = scif_info.nodeid;
  88. msg.dst.node = SCIF_MGMT_NODE;
  89. msg.payload[0] = dev->node;
  90. scif_nodeqp_send(&scif_dev[SCIF_MGMT_NODE], &msg);
  91. dev->node_remove_ack_pending = false;
  92. }
  93. if (dev->exit_ack_pending) {
  94. msg.uop = SCIF_EXIT_ACK;
  95. msg.src.node = scif_info.nodeid;
  96. msg.dst.node = dev->node;
  97. scif_nodeqp_send(dev, &msg);
  98. dev->exit_ack_pending = false;
  99. }
  100. }
  101. /*
  102. * scif_cleanup_scifdev
  103. *
  104. * @dev: Remote SCIF device.
  105. * Uninitialize SCIF data structures for remote SCIF device.
  106. */
  107. void scif_cleanup_scifdev(struct scif_dev *dev)
  108. {
  109. struct scif_hw_dev *sdev = dev->sdev;
  110. if (!dev->sdev)
  111. return;
  112. if (scifdev_is_p2p(dev)) {
  113. if (dev->cookie) {
  114. sdev->hw_ops->free_irq(sdev, dev->cookie, dev);
  115. dev->cookie = NULL;
  116. }
  117. scif_destroy_intr_wq(dev);
  118. }
  119. flush_work(&scif_info.misc_work);
  120. scif_destroy_p2p(dev);
  121. scif_invalidate_ep(dev->node);
  122. scif_zap_mmaps(dev->node);
  123. scif_cleanup_rma_for_zombies(dev->node);
  124. flush_work(&scif_info.misc_work);
  125. scif_send_acks(dev);
  126. if (!dev->node && scif_info.card_initiated_exit) {
  127. /*
  128. * Send an SCIF_EXIT message which is the last message from MIC
  129. * to the Host and wait for a SCIF_EXIT_ACK
  130. */
  131. scif_send_exit(dev);
  132. scif_info.card_initiated_exit = false;
  133. }
  134. scif_cleanup_qp(dev);
  135. }
  136. /*
  137. * scif_remove_node:
  138. *
  139. * @node: Node to remove
  140. */
  141. void scif_handle_remove_node(int node)
  142. {
  143. struct scif_dev *scifdev = &scif_dev[node];
  144. if (scif_peer_unregister_device(scifdev))
  145. scif_send_acks(scifdev);
  146. }
  147. static int scif_send_rmnode_msg(int node, int remove_node)
  148. {
  149. struct scifmsg notif_msg;
  150. struct scif_dev *dev = &scif_dev[node];
  151. notif_msg.uop = SCIF_NODE_REMOVE;
  152. notif_msg.src.node = scif_info.nodeid;
  153. notif_msg.dst.node = node;
  154. notif_msg.payload[0] = remove_node;
  155. return scif_nodeqp_send(dev, &notif_msg);
  156. }
  157. /**
  158. * scif_node_disconnect:
  159. *
  160. * @node_id[in]: source node id.
  161. * @mgmt_initiated: Disconnection initiated from the mgmt node
  162. *
  163. * Disconnect a node from the scif network.
  164. */
  165. void scif_disconnect_node(u32 node_id, bool mgmt_initiated)
  166. {
  167. int ret;
  168. int msg_cnt = 0;
  169. u32 i = 0;
  170. struct scif_dev *scifdev = &scif_dev[node_id];
  171. if (!node_id)
  172. return;
  173. atomic_set(&scifdev->disconn_rescnt, 0);
  174. /* Destroy p2p network */
  175. for (i = 1; i <= scif_info.maxid; i++) {
  176. if (i == node_id)
  177. continue;
  178. ret = scif_send_rmnode_msg(i, node_id);
  179. if (!ret)
  180. msg_cnt++;
  181. }
  182. /* Wait for the remote nodes to respond with SCIF_NODE_REMOVE_ACK */
  183. ret = wait_event_timeout(scifdev->disconn_wq,
  184. (atomic_read(&scifdev->disconn_rescnt)
  185. == msg_cnt), SCIF_NODE_ALIVE_TIMEOUT);
  186. /* Tell the card to clean up */
  187. if (mgmt_initiated && _scifdev_alive(scifdev))
  188. /*
  189. * Send an SCIF_EXIT message which is the last message from Host
  190. * to the MIC and wait for a SCIF_EXIT_ACK
  191. */
  192. scif_send_exit(scifdev);
  193. atomic_set(&scifdev->disconn_rescnt, 0);
  194. /* Tell the mgmt node to clean up */
  195. ret = scif_send_rmnode_msg(SCIF_MGMT_NODE, node_id);
  196. if (!ret)
  197. /* Wait for mgmt node to respond with SCIF_NODE_REMOVE_ACK */
  198. wait_event_timeout(scifdev->disconn_wq,
  199. (atomic_read(&scifdev->disconn_rescnt) == 1),
  200. SCIF_NODE_ALIVE_TIMEOUT);
  201. }
  202. void scif_get_node_info(void)
  203. {
  204. struct scifmsg msg;
  205. DECLARE_COMPLETION_ONSTACK(node_info);
  206. msg.uop = SCIF_GET_NODE_INFO;
  207. msg.src.node = scif_info.nodeid;
  208. msg.dst.node = SCIF_MGMT_NODE;
  209. msg.payload[3] = (u64)&node_info;
  210. if ((scif_nodeqp_send(&scif_dev[SCIF_MGMT_NODE], &msg)))
  211. return;
  212. /* Wait for a response with SCIF_GET_NODE_INFO */
  213. wait_for_completion(&node_info);
  214. }