scif_nm.c 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  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. spin_lock(&ep->lock);
  35. scif_cleanup_ep_qp(ep);
  36. spin_unlock(&ep->lock);
  37. }
  38. }
  39. list_for_each_safe(pos, tmpq, &scif_info.connected) {
  40. ep = list_entry(pos, struct scif_endpt, list);
  41. if (ep->remote_dev->node == node) {
  42. list_del(pos);
  43. spin_lock(&ep->lock);
  44. ep->state = SCIFEP_DISCONNECTED;
  45. list_add_tail(&ep->list, &scif_info.disconnected);
  46. scif_cleanup_ep_qp(ep);
  47. wake_up_interruptible(&ep->sendwq);
  48. wake_up_interruptible(&ep->recvwq);
  49. spin_unlock(&ep->lock);
  50. }
  51. }
  52. mutex_unlock(&scif_info.connlock);
  53. }
  54. void scif_free_qp(struct scif_dev *scifdev)
  55. {
  56. struct scif_qp *qp = scifdev->qpairs;
  57. if (!qp)
  58. return;
  59. scif_free_coherent((void *)qp->inbound_q.rb_base,
  60. qp->local_buf, scifdev, qp->inbound_q.size);
  61. scif_unmap_single(qp->local_qp, scifdev, sizeof(struct scif_qp));
  62. kfree(scifdev->qpairs);
  63. scifdev->qpairs = NULL;
  64. }
  65. static void scif_cleanup_qp(struct scif_dev *dev)
  66. {
  67. struct scif_qp *qp = &dev->qpairs[0];
  68. if (!qp)
  69. return;
  70. scif_iounmap((void *)qp->remote_qp, sizeof(struct scif_qp), dev);
  71. scif_iounmap((void *)qp->outbound_q.rb_base,
  72. sizeof(struct scif_qp), dev);
  73. qp->remote_qp = NULL;
  74. qp->local_write = 0;
  75. qp->inbound_q.current_write_offset = 0;
  76. qp->inbound_q.current_read_offset = 0;
  77. if (scifdev_is_p2p(dev))
  78. scif_free_qp(dev);
  79. }
  80. void scif_send_acks(struct scif_dev *dev)
  81. {
  82. struct scifmsg msg;
  83. if (dev->node_remove_ack_pending) {
  84. msg.uop = SCIF_NODE_REMOVE_ACK;
  85. msg.src.node = scif_info.nodeid;
  86. msg.dst.node = SCIF_MGMT_NODE;
  87. msg.payload[0] = dev->node;
  88. scif_nodeqp_send(&scif_dev[SCIF_MGMT_NODE], &msg);
  89. dev->node_remove_ack_pending = false;
  90. }
  91. if (dev->exit_ack_pending) {
  92. msg.uop = SCIF_EXIT_ACK;
  93. msg.src.node = scif_info.nodeid;
  94. msg.dst.node = dev->node;
  95. scif_nodeqp_send(dev, &msg);
  96. dev->exit_ack_pending = false;
  97. }
  98. }
  99. /*
  100. * scif_cleanup_scifdev
  101. *
  102. * @dev: Remote SCIF device.
  103. * Uninitialize SCIF data structures for remote SCIF device.
  104. */
  105. void scif_cleanup_scifdev(struct scif_dev *dev)
  106. {
  107. struct scif_hw_dev *sdev = dev->sdev;
  108. if (!dev->sdev)
  109. return;
  110. if (scifdev_is_p2p(dev)) {
  111. if (dev->cookie) {
  112. sdev->hw_ops->free_irq(sdev, dev->cookie, dev);
  113. dev->cookie = NULL;
  114. }
  115. scif_destroy_intr_wq(dev);
  116. }
  117. scif_destroy_p2p(dev);
  118. scif_invalidate_ep(dev->node);
  119. scif_send_acks(dev);
  120. if (!dev->node && scif_info.card_initiated_exit) {
  121. /*
  122. * Send an SCIF_EXIT message which is the last message from MIC
  123. * to the Host and wait for a SCIF_EXIT_ACK
  124. */
  125. scif_send_exit(dev);
  126. scif_info.card_initiated_exit = false;
  127. }
  128. scif_cleanup_qp(dev);
  129. }
  130. /*
  131. * scif_remove_node:
  132. *
  133. * @node: Node to remove
  134. */
  135. void scif_handle_remove_node(int node)
  136. {
  137. struct scif_dev *scifdev = &scif_dev[node];
  138. struct scif_peer_dev *spdev;
  139. rcu_read_lock();
  140. spdev = rcu_dereference(scifdev->spdev);
  141. rcu_read_unlock();
  142. if (spdev)
  143. scif_peer_unregister_device(spdev);
  144. else
  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. }