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

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