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.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. /*
  2. * Copyright (C) 2008 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., 51 Franklin Street, Fifth Floor, Boston, MA
  17. * 02110-1301, USA.
  18. *
  19. * You can also choose to distribute this program under the terms of
  20. * the Unmodified Binary Distribution Licence (as given in the file
  21. * COPYING.UBDL), provided that you have satisfied its requirements.
  22. */
  23. FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
  24. #include <stdint.h>
  25. #include <stdlib.h>
  26. #include <string.h>
  27. #include <errno.h>
  28. #include <unistd.h>
  29. #include <byteswap.h>
  30. #include <ipxe/infiniband.h>
  31. #include <ipxe/ib_smc.h>
  32. /**
  33. * @file
  34. *
  35. * Infiniband Subnet Management Client
  36. *
  37. */
  38. /**
  39. * Issue local MAD
  40. *
  41. * @v ibdev Infiniband device
  42. * @v attr_id Attribute ID, in network byte order
  43. * @v attr_mod Attribute modifier, in network byte order
  44. * @v local_mad Method for issuing local MADs
  45. * @v mad Management datagram to fill in
  46. * @ret rc Return status code
  47. */
  48. static int ib_smc_mad ( struct ib_device *ibdev, uint16_t attr_id,
  49. uint32_t attr_mod, ib_local_mad_t local_mad,
  50. union ib_mad *mad ) {
  51. int rc;
  52. /* Construct MAD */
  53. memset ( mad, 0, sizeof ( *mad ) );
  54. mad->hdr.base_version = IB_MGMT_BASE_VERSION;
  55. mad->hdr.mgmt_class = IB_MGMT_CLASS_SUBN_LID_ROUTED;
  56. mad->hdr.class_version = 1;
  57. mad->hdr.method = IB_MGMT_METHOD_GET;
  58. mad->hdr.attr_id = attr_id;
  59. mad->hdr.attr_mod = attr_mod;
  60. /* Issue MAD */
  61. if ( ( rc = local_mad ( ibdev, mad ) ) != 0 )
  62. return rc;
  63. return 0;
  64. }
  65. /**
  66. * Get node information
  67. *
  68. * @v ibdev Infiniband device
  69. * @v local_mad Method for issuing local MADs
  70. * @v mad Management datagram to fill in
  71. * @ret rc Return status code
  72. */
  73. static int ib_smc_get_node_info ( struct ib_device *ibdev,
  74. ib_local_mad_t local_mad,
  75. union ib_mad *mad ) {
  76. int rc;
  77. /* Issue MAD */
  78. if ( ( rc = ib_smc_mad ( ibdev, htons ( IB_SMP_ATTR_NODE_INFO ), 0,
  79. local_mad, mad ) ) != 0 ) {
  80. DBGC ( ibdev, "IBDEV %s could not get node info: %s\n",
  81. ibdev->name, strerror ( rc ) );
  82. return rc;
  83. }
  84. return 0;
  85. }
  86. /**
  87. * Get port information
  88. *
  89. * @v ibdev Infiniband device
  90. * @v local_mad Method for issuing local MADs
  91. * @v mad Management datagram to fill in
  92. * @ret rc Return status code
  93. */
  94. static int ib_smc_get_port_info ( struct ib_device *ibdev,
  95. ib_local_mad_t local_mad,
  96. union ib_mad *mad ) {
  97. int rc;
  98. /* Issue MAD */
  99. if ( ( rc = ib_smc_mad ( ibdev, htons ( IB_SMP_ATTR_PORT_INFO ),
  100. htonl ( ibdev->port ), local_mad, mad )) !=0){
  101. DBGC ( ibdev, "IBDEV %s could not get port info: %s\n",
  102. ibdev->name, strerror ( rc ) );
  103. return rc;
  104. }
  105. return 0;
  106. }
  107. /**
  108. * Get GUID information
  109. *
  110. * @v ibdev Infiniband device
  111. * @v local_mad Method for issuing local MADs
  112. * @v mad Management datagram to fill in
  113. * @ret rc Return status code
  114. */
  115. static int ib_smc_get_guid_info ( struct ib_device *ibdev,
  116. ib_local_mad_t local_mad,
  117. union ib_mad *mad ) {
  118. int rc;
  119. /* Issue MAD */
  120. if ( ( rc = ib_smc_mad ( ibdev, htons ( IB_SMP_ATTR_GUID_INFO ), 0,
  121. local_mad, mad ) ) != 0 ) {
  122. DBGC ( ibdev, "IBDEV %s could not get GUID info: %s\n",
  123. ibdev->name, strerror ( rc ) );
  124. return rc;
  125. }
  126. return 0;
  127. }
  128. /**
  129. * Get partition key table
  130. *
  131. * @v ibdev Infiniband device
  132. * @v local_mad Method for issuing local MADs
  133. * @v mad Management datagram to fill in
  134. * @ret rc Return status code
  135. */
  136. static int ib_smc_get_pkey_table ( struct ib_device *ibdev,
  137. ib_local_mad_t local_mad,
  138. union ib_mad *mad ) {
  139. int rc;
  140. /* Issue MAD */
  141. if ( ( rc = ib_smc_mad ( ibdev, htons ( IB_SMP_ATTR_PKEY_TABLE ), 0,
  142. local_mad, mad ) ) != 0 ) {
  143. DBGC ( ibdev, "IBDEV %s could not get pkey table: %s\n",
  144. ibdev->name, strerror ( rc ) );
  145. return rc;
  146. }
  147. return 0;
  148. }
  149. /**
  150. * Get Infiniband parameters using SMC
  151. *
  152. * @v ibdev Infiniband device
  153. * @v local_mad Method for issuing local MADs
  154. * @ret rc Return status code
  155. */
  156. static int ib_smc_get ( struct ib_device *ibdev, ib_local_mad_t local_mad ) {
  157. union ib_mad mad;
  158. struct ib_node_info *node_info = &mad.smp.smp_data.node_info;
  159. struct ib_port_info *port_info = &mad.smp.smp_data.port_info;
  160. struct ib_guid_info *guid_info = &mad.smp.smp_data.guid_info;
  161. struct ib_pkey_table *pkey_table = &mad.smp.smp_data.pkey_table;
  162. int rc;
  163. /* Node info gives us the node GUID */
  164. if ( ( rc = ib_smc_get_node_info ( ibdev, local_mad, &mad ) ) != 0 )
  165. return rc;
  166. memcpy ( &ibdev->node_guid, &node_info->node_guid,
  167. sizeof ( ibdev->node_guid ) );
  168. /* Port info gives us the link state, the first half of the
  169. * port GID and the SM LID.
  170. */
  171. if ( ( rc = ib_smc_get_port_info ( ibdev, local_mad, &mad ) ) != 0 )
  172. return rc;
  173. memcpy ( &ibdev->gid.s.prefix, port_info->gid_prefix,
  174. sizeof ( ibdev->gid.s.prefix ) );
  175. ibdev->lid = ntohs ( port_info->lid );
  176. ibdev->sm_lid = ntohs ( port_info->mastersm_lid );
  177. ibdev->link_width_enabled = port_info->link_width_enabled;
  178. ibdev->link_width_supported = port_info->link_width_supported;
  179. ibdev->link_width_active = port_info->link_width_active;
  180. ibdev->link_speed_supported =
  181. ( port_info->link_speed_supported__port_state >> 4 );
  182. ibdev->port_state =
  183. ( port_info->link_speed_supported__port_state & 0xf );
  184. ibdev->link_speed_active =
  185. ( port_info->link_speed_active__link_speed_enabled >> 4 );
  186. ibdev->link_speed_enabled =
  187. ( port_info->link_speed_active__link_speed_enabled & 0xf );
  188. ibdev->sm_sl = ( port_info->neighbour_mtu__mastersm_sl & 0xf );
  189. /* GUID info gives us the second half of the port GID */
  190. if ( ( rc = ib_smc_get_guid_info ( ibdev, local_mad, &mad ) ) != 0 )
  191. return rc;
  192. memcpy ( &ibdev->gid.s.guid, guid_info->guid[0],
  193. sizeof ( ibdev->gid.s.guid ) );
  194. /* Get partition key */
  195. if ( ( rc = ib_smc_get_pkey_table ( ibdev, local_mad, &mad ) ) != 0 )
  196. return rc;
  197. ibdev->pkey = ntohs ( pkey_table->pkey[0] );
  198. DBGC ( ibdev, "IBDEV %s port GID is " IB_GID_FMT "\n",
  199. ibdev->name, IB_GID_ARGS ( &ibdev->gid ) );
  200. return 0;
  201. }
  202. /**
  203. * Initialise Infiniband parameters using SMC
  204. *
  205. * @v ibdev Infiniband device
  206. * @v local_mad Method for issuing local MADs
  207. * @ret rc Return status code
  208. */
  209. int ib_smc_init ( struct ib_device *ibdev, ib_local_mad_t local_mad ) {
  210. int rc;
  211. /* Get MAD parameters */
  212. if ( ( rc = ib_smc_get ( ibdev, local_mad ) ) != 0 )
  213. return rc;
  214. return 0;
  215. }
  216. /**
  217. * Update Infiniband parameters using SMC
  218. *
  219. * @v ibdev Infiniband device
  220. * @v local_mad Method for issuing local MADs
  221. * @ret rc Return status code
  222. */
  223. int ib_smc_update ( struct ib_device *ibdev, ib_local_mad_t local_mad ) {
  224. int rc;
  225. /* Get MAD parameters */
  226. if ( ( rc = ib_smc_get ( ibdev, local_mad ) ) != 0 )
  227. return rc;
  228. /* Notify Infiniband core of potential link state change */
  229. ib_link_state_changed ( ibdev );
  230. return 0;
  231. }