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 4.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  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 CQ: %s\n",
  56. ibdev, strerror ( rc ) );
  57. free ( cq );
  58. return NULL;
  59. }
  60. DBGC ( ibdev, "IBDEV %p created completion queue %#lx\n",
  61. ibdev, 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. * Find work queue belonging to completion queue
  80. *
  81. * @v cq Completion queue
  82. * @v qpn Queue pair number
  83. * @v is_send Find send work queue (rather than receive)
  84. * @ret wq Work queue, or NULL if not found
  85. */
  86. struct ib_work_queue * ib_find_wq ( struct ib_completion_queue *cq,
  87. unsigned long qpn, int is_send ) {
  88. struct ib_work_queue *wq;
  89. list_for_each_entry ( wq, &cq->work_queues, list ) {
  90. if ( ( wq->qp->qpn == qpn ) && ( wq->is_send == is_send ) )
  91. return wq;
  92. }
  93. return NULL;
  94. }
  95. /** Infiniband broadcast MAC address */
  96. static uint8_t ib_broadcast[IB_ALEN] = { 0xff, };
  97. /**
  98. * Transmit Infiniband packet
  99. *
  100. * @v iobuf I/O buffer
  101. * @v netdev Network device
  102. * @v net_protocol Network-layer protocol
  103. * @v ll_dest Link-layer destination address
  104. *
  105. * Prepends the Infiniband link-layer header and transmits the packet.
  106. */
  107. static int ib_tx ( struct io_buffer *iobuf, struct net_device *netdev,
  108. struct net_protocol *net_protocol, const void *ll_dest ) {
  109. struct ibhdr *ibhdr = iob_push ( iobuf, sizeof ( *ibhdr ) );
  110. /* Build Infiniband header */
  111. ibhdr->proto = net_protocol->net_proto;
  112. ibhdr->reserved = 0;
  113. ( void ) ll_dest;
  114. /* Hand off to network device */
  115. return netdev_tx ( netdev, iobuf );
  116. }
  117. /**
  118. * Process received Infiniband packet
  119. *
  120. * @v iobuf I/O buffer
  121. * @v netdev Network device
  122. *
  123. * Strips off the Infiniband link-layer header and passes up to the
  124. * network-layer protocol.
  125. */
  126. static int ib_rx ( struct io_buffer *iobuf, struct net_device *netdev ) {
  127. struct ibhdr *ibhdr = iobuf->data;
  128. /* Sanity check */
  129. if ( iob_len ( iobuf ) < sizeof ( *ibhdr ) ) {
  130. DBG ( "Infiniband packet too short (%d bytes)\n",
  131. iob_len ( iobuf ) );
  132. free_iob ( iobuf );
  133. return -EINVAL;
  134. }
  135. /* Strip off Infiniband header */
  136. iob_pull ( iobuf, sizeof ( *ibhdr ) );
  137. /* Hand off to network-layer protocol */
  138. return net_rx ( iobuf, netdev, ibhdr->proto, NULL );
  139. }
  140. /**
  141. * Transcribe Infiniband address
  142. *
  143. * @v ll_addr Link-layer address
  144. * @ret string Link-layer address in human-readable format
  145. */
  146. const char * ib_ntoa ( const void *ll_addr ) {
  147. static char buf[61];
  148. const uint8_t *ib_addr = ll_addr;
  149. unsigned int i;
  150. char *p = buf;
  151. for ( i = 0 ; i < IB_ALEN ; i++ ) {
  152. p += sprintf ( p, ":%02x", ib_addr[i] );
  153. }
  154. return ( buf + 1 );
  155. }
  156. /** Infiniband protocol */
  157. struct ll_protocol infiniband_protocol __ll_protocol = {
  158. .name = "Infiniband",
  159. .ll_proto = htons ( ARPHRD_INFINIBAND ),
  160. .ll_addr_len = IB_ALEN,
  161. .ll_header_len = IB_HLEN,
  162. .ll_broadcast = ib_broadcast,
  163. .tx = ib_tx,
  164. .rx = ib_rx,
  165. .ntoa = ib_ntoa,
  166. };