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.

ib_smc.c 6.9KB

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