You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

infiniband.c 5.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. /*
  2. * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
  3. *
  4. * This program is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU General Public License as
  6. * published by the Free Software Foundation; either version 2 of the
  7. * License, or any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful, but
  10. * WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. * General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program; if not, write to the Free Software
  16. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17. */
  18. #include <stdint.h>
  19. #include <stdlib.h>
  20. #include <stdio.h>
  21. #include <string.h>
  22. #include <byteswap.h>
  23. #include <errno.h>
  24. #include <assert.h>
  25. #include <gpxe/list.h>
  26. #include <gpxe/if_arp.h>
  27. #include <gpxe/netdevice.h>
  28. #include <gpxe/iobuf.h>
  29. #include <gpxe/infiniband.h>
  30. /** @file
  31. *
  32. * Infiniband protocol
  33. *
  34. */
  35. /**
  36. * Create completion queue
  37. *
  38. * @v ibdev Infiniband device
  39. * @v num_cqes Number of completion queue entries
  40. * @ret cq New completion queue
  41. */
  42. struct ib_completion_queue * ib_create_cq ( struct ib_device *ibdev,
  43. unsigned int num_cqes ) {
  44. struct ib_completion_queue *cq;
  45. int rc;
  46. DBGC ( ibdev, "IBDEV %p creating completion queue\n", ibdev );
  47. /* Allocate and initialise data structure */
  48. cq = zalloc ( sizeof ( *cq ) );
  49. if ( ! cq )
  50. return NULL;
  51. cq->num_cqes = num_cqes;
  52. INIT_LIST_HEAD ( &cq->work_queues );
  53. /* Perform device-specific initialisation and get CQN */
  54. if ( ( rc = ibdev->op->create_cq ( ibdev, cq ) ) != 0 ) {
  55. DBGC ( ibdev, "IBDEV %p could not initialise completion "
  56. "queue: %s\n", ibdev, strerror ( rc ) );
  57. free ( cq );
  58. return NULL;
  59. }
  60. DBGC ( ibdev, "IBDEV %p created %d-entry completion queue %p (%p) "
  61. "with CQN %#lx\n", ibdev, num_cqes, cq, cq->dev_priv, cq->cqn );
  62. return cq;
  63. }
  64. /**
  65. * Destroy completion queue
  66. *
  67. * @v ibdev Infiniband device
  68. * @v cq Completion queue
  69. */
  70. void ib_destroy_cq ( struct ib_device *ibdev,
  71. struct ib_completion_queue *cq ) {
  72. DBGC ( ibdev, "IBDEV %p destroying completion queue %#lx\n",
  73. ibdev, cq->cqn );
  74. assert ( list_empty ( &cq->work_queues ) );
  75. ibdev->op->destroy_cq ( ibdev, cq );
  76. free ( cq );
  77. }
  78. /**
  79. * Create queue pair
  80. *
  81. * @v ibdev Infiniband device
  82. * @v num_send_wqes Number of send work queue entries
  83. * @v send_cq Send completion queue
  84. * @v num_recv_wqes Number of receive work queue entries
  85. * @v recv_cq Receive completion queue
  86. * @v qkey Queue key
  87. * @ret qp Queue pair
  88. */
  89. struct ib_queue_pair * ib_create_qp ( struct ib_device *ibdev,
  90. unsigned int num_send_wqes,
  91. struct ib_completion_queue *send_cq,
  92. unsigned int num_recv_wqes,
  93. struct ib_completion_queue *recv_cq,
  94. unsigned long qkey ) {
  95. struct ib_queue_pair *qp;
  96. size_t total_size;
  97. int rc;
  98. DBGC ( ibdev, "IBDEV %p creating queue pair\n", ibdev );
  99. /* Allocate and initialise data structure */
  100. total_size = ( sizeof ( *qp ) +
  101. ( num_send_wqes * sizeof ( qp->send.iobufs[0] ) ) +
  102. ( num_recv_wqes * sizeof ( qp->recv.iobufs[0] ) ) );
  103. qp = zalloc ( total_size );
  104. if ( ! qp )
  105. return NULL;
  106. qp->qkey = qkey;
  107. qp->send.qp = qp;
  108. qp->send.is_send = 1;
  109. qp->send.cq = send_cq;
  110. list_add ( &qp->send.list, &send_cq->work_queues );
  111. qp->send.num_wqes = num_send_wqes;
  112. qp->send.iobufs = ( ( ( void * ) qp ) + sizeof ( *qp ) );
  113. qp->recv.qp = qp;
  114. qp->recv.cq = recv_cq;
  115. list_add ( &qp->recv.list, &recv_cq->work_queues );
  116. qp->recv.num_wqes = num_recv_wqes;
  117. qp->recv.iobufs = ( ( ( void * ) qp ) + sizeof ( *qp ) +
  118. ( num_send_wqes * sizeof ( qp->send.iobufs[0] ) ));
  119. /* Perform device-specific initialisation and get QPN */
  120. if ( ( rc = ibdev->op->create_qp ( ibdev, qp ) ) != 0 ) {
  121. DBGC ( ibdev, "IBDEV %p could not initialise queue pair: "
  122. "%s\n", ibdev, strerror ( rc ) );
  123. free ( qp );
  124. return NULL;
  125. }
  126. DBGC ( ibdev, "IBDEV %p created queue pair %p (%p) with QPN %#lx\n",
  127. ibdev, qp, qp->dev_priv, qp->qpn );
  128. DBGC ( ibdev, "IBDEV %p QPN %#lx has %d send entries at [%p,%p)\n",
  129. ibdev, qp->qpn, num_send_wqes, qp->send.iobufs,
  130. qp->recv.iobufs );
  131. DBGC ( ibdev, "IBDEV %p QPN %#lx has %d receive entries at [%p,%p)\n",
  132. ibdev, qp->qpn, num_send_wqes, qp->recv.iobufs,
  133. ( ( ( void * ) qp ) + total_size ) );
  134. return qp;
  135. }
  136. /**
  137. * Destroy queue pair
  138. *
  139. * @v ibdev Infiniband device
  140. * @v qp Queue pair
  141. */
  142. void ib_destroy_qp ( struct ib_device *ibdev,
  143. struct ib_queue_pair *qp ) {
  144. DBGC ( ibdev, "IBDEV %p destroying queue pair %#lx\n",
  145. ibdev, qp->qpn );
  146. ibdev->op->destroy_qp ( ibdev, qp );
  147. list_del ( &qp->send.list );
  148. list_del ( &qp->recv.list );
  149. free ( qp );
  150. }
  151. /**
  152. * Find work queue belonging to completion queue
  153. *
  154. * @v cq Completion queue
  155. * @v qpn Queue pair number
  156. * @v is_send Find send work queue (rather than receive)
  157. * @ret wq Work queue, or NULL if not found
  158. */
  159. struct ib_work_queue * ib_find_wq ( struct ib_completion_queue *cq,
  160. unsigned long qpn, int is_send ) {
  161. struct ib_work_queue *wq;
  162. list_for_each_entry ( wq, &cq->work_queues, list ) {
  163. if ( ( wq->qp->qpn == qpn ) && ( wq->is_send == is_send ) )
  164. return wq;
  165. }
  166. return NULL;
  167. }
  168. /**
  169. * Allocate Infiniband device
  170. *
  171. * @v priv_size Size of private data area
  172. * @ret ibdev Infiniband device, or NULL
  173. */
  174. struct ib_device * alloc_ibdev ( size_t priv_size ) {
  175. struct ib_device *ibdev;
  176. size_t total_len;
  177. total_len = ( sizeof ( *ibdev ) + priv_size );
  178. ibdev = zalloc ( total_len );
  179. if ( ibdev ) {
  180. ibdev->dev_priv = ( ( ( void * ) ibdev ) + sizeof ( *ibdev ) );
  181. }
  182. return ibdev;
  183. }
  184. /**
  185. * Free Infiniband device
  186. *
  187. * @v ibdev Infiniband device
  188. */
  189. void free_ibdev ( struct ib_device *ibdev ) {
  190. free ( ibdev );
  191. }